360笔试



这道题想了下还有种方法

import java.util.*;

/**
 * Created by Administrator on 2018/8/29.
 */
public class Test3 {

    public static void main(String[] args) {
        Scanner cin=new Scanner(System.in);
        int n=cin.nextInt();
        int m=cin.nextInt();
        int[] count=new int[n];
        for (int i = 0; i < count.length; i++) {
            count[i]=cin.nextInt();
        }
        int ques=cin.nextInt();
        int[][] visit=new int[ques][2];
        for (int i = 0; i < ques; i++) {
            visit[i][0]=cin.nextInt();
            visit[i][1]=cin.nextInt();
        }
       List<Integer> list= getList(n,m,count,visit);
        Iterator it=list.iterator();

       while (it.hasNext()){
           System.out.println(it.next());
       }
    }

    public static List<Integer> getList(int n,int m,int[] count,int[][] visit){
        List<Integer> res=new ArrayList<>();
        for(int i=0;i<visit.length;++i){//开始小红的Q个问题
            Set<Integer> set=new HashSet<>();//因为记录小明看花的种类,重复的不算,所以用set
            for (int j = visit[i][0]-1; j <visit[i][1]-1 ; j++) {//j从小红的问的第l次到r次,减一是因为下标从0开始
                set.add(count[j]);//第j次所对应的count[j]的值,也就是小明看花的种类:count[j]
            }
            res.add(set.size());//set.size()也就是小明看过的种类总数
        }
        return res;
    }

}

LeetCode 64. Minimum Path Sum


看这个例子


首先申请一个和原数组一样大小的数组tempGrid,然后把第一行所有列和第一列所有行的最短路径求出来。

第一行

  for(int i=1;i<grid[0].length;++i){
            tempGrid[0][i]=tempGrid[0][i-1]+grid[0][i];
        }

第一列

 for(int i=1;i<grid.length;++i){
            tempGrid[i][0]=tempGrid[i-1][0]+grid[i][0];
        }

tempGrid数组变成

然后中间的一些元素按照以下方式填充

 for(int i=1;i<grid.length;++i){
            for(int j=1;j<grid[0].length;++j){
                tempGrid[i][j]=Math.min(tempGrid[i-1][j]+grid[i][j],tempGrid[i][j-1]+grid[i][j]);
            }
        }


public static int minPathSum(int[][] grid) {

        int[][] tempGrid=new int[grid.length][grid[0].length];
        tempGrid[0][0]=grid[0][0];
        for(int i=1;i<grid[0].length;++i){
            tempGrid[0][i]=tempGrid[0][i-1]+grid[0][i];
        }
        for(int i=1;i<grid.length;++i){
            tempGrid[i][0]=tempGrid[i-1][0]+grid[i][0];
        }
        for(int i=1;i<grid.length;++i){
            for(int j=1;j<grid[0].length;++j){
                tempGrid[i][j]=Math.min(tempGrid[i-1][j]+grid[i][j],tempGrid[i][j-1]+grid[i][j]);
            }
        }

        return tempGrid[grid.length-1][grid[0].length-1];
    }

参考:

https://www.youtube.com/watch?v=lBRtnuxg-gU


可靠数据传输原理 三 TCP协议


TCP概述:RFCs-793,1122,1323,2018,2581

点对点

一个发送方,一个接收方。不支持一对多,比如一个发送方多个接收方

tcp使用流水线机制

TCP拥塞控制和流量控制机制设置窗口尺寸。
至于窗口尺寸的设置是一个比较复杂的事情了,他是基于拥塞控制和流量控制机制来动态调整窗口尺寸

发送方和接收方都设置缓存

他结合GBN和SR协议,发送方接收方都设置缓存

面向连接

  • 通信双方在发送数据之前必须建立链接。
  • 链接状态只在链接的两端中维护,在沿途节点中并不维护状态。
  • TCP链接包括:两台主机的缓存,链接状态变量,socket等

全双工

同一个连接中能够传输双向数据流

tcp的段结构

在tcp段结构中很多字段都还没有用,存在很多改进空间。

recevie window
所愿意接收的字节的字节数,来进行流量控制

序列号:

  • 序列号指的是segment中的第一个字节的编号,而不是segemnt的编号
  • 建立TCP连接时,双方随即选择序列号

不是segment的第几个这样的编号,而是第一个字节的编号
随机选择序列号,在链接之后,回互相交换信息

ACKs:

  • 希望收到的下一个字节的序列号
  • 累计确认:该序列号之前的所有字节均已被正确接收

acks表示下一个期望接收到的序列号的值
注意也是累计确认的有点像GBN

接收方如何处理乱序到达的Segement?

  • TCP规范中没有规定,由TCP的实现者做出决策

看一个例子

  1. 第一条线是在tcp链接已经建立的情况下,段的序列号是序列号是随机选择的。下一个期望接收到的序列号是79
  2. 主机b 返回的段的序列号为79,下一个期望接受到的为43。与此同时43之前的都已经被确认了
  3. 之后主机a要再发一个确认,这时候data里面不带任何数据。序列号变成了43,ack变成了80

之前看了大量的可靠传输的原理,下面来看tcp是用到了哪些可靠传输的原理来实现可靠传输服务的。

IP层是不可靠的,tcp要把他转换为可靠的服务

  • TCP在IP层提供的不可靠服务基础上实现可靠数据传输服务
  • 流水线机制
  • 累计确认
  • Tcp使用单一重传定时器

后面要了解下单一计时器是怎么使用的


可靠数据传输原理 二 滑动窗口协议之SR协议


SR协议是滑动窗口协议的另外一类。


GBN协议的缺陷是重传的时候,传很多个之前传过去的分组。比如当序列号n开始重传,那就回传n及n以后所有的未确认的分组。那么我们是否可以考虑不使用累积确认机制,进行单个确认,然后我们也不丢弃乱序的分组,而是将他们缓存起来,这就是SR协议。

设置缓存,可以接受乱序到达的分组

超过定时器时间重传,但是只重传自己


可靠数据传输原理 二 滑动窗口协议之GBN协议


Rdt3.0的性能太低了,显然需要改进它
如果细究这个效率太低的原因,那就是停等操作导致的。所以要打破停等机制,可以在等的同时,继续发送其他分组。

回顾这张图

Usender:效率
由于要等待RTT这个时间才能发下一个分组,所以效率很低。

流水线机制,可以提高资源利用率


比如一次性发三个。效率提高三倍

流水线协议


序列号也多了,一个分组用一个序列号。
之前是发一个 然后要等,所以先缓存起来,然后等确认后删除,现在是多个需要同时缓存起来了。

可以看到流水线机制,就是同时发多个分组在路上,然后返回ack的时候也有多个ack在路上

滑动窗口协议

要想实现流水线机制,需要滑动窗口协议


这些小竖条是一共可以提供使用的序列号的数量(k比特的话就是2^k次方个可用的序列号)。
窗口左边是已经发送并且已经确认了的,黄色的是发出去了,但是还没收到确认的。蓝色的是代表,剩余的可以用来发送的序列号,白色的是哪些还不能使用的序列号,因为你的窗口还没有滑动到那里。

两种滑动窗口协议:GBN,SR

后退N帧(GBN)协议(意思是从没接受到的ack的那个分组开始发送,就算后面的收到了,也都重新发送一遍?)


k-bit序列号意味着2的k次方个序列号可以用
最多n个分组未确认

【重】在来看看滑动窗口的结构

这些小竖条是一共可以提供使用的序列号的数量(k比特的话就是2^k次方个可用的序列号)。
窗口左边是已经发送并且已经确认了的,黄色的是发出去了,但是还没收到确认的。蓝色的是代表,窗口内剩余的可以用来发送的序列号,白色的是哪些还不能使用的序列号,因为你的窗口还没有滑动到那里。

GBN协议(理解的不够深)
是采用一种累积确认的机制(也就是会从一到...,n-1,到n一个个累积),当他ack(为n)的时候,说明都已经被确认了

毫无疑问,也是要为每一个分组设置定时器的,然后如果超过一定时间,即timeout了,那就会重发所有未收到的ack的以及后面的分组(比如第k个timeout了,那就会重发序列号为k+1,k+2,...,n-1,n的所有分组)。

上面的方式会造成资源的浪费

流水线机制就可能导致分组的ack乱序到达,gbn处理的方式是,直接丢掉哪些不是期望收到的ack序列号


可以看到当收到pkt3的时候直接丢弃发送ack1,因为收到pkt0,pkt1后,没有收到pkt2.直到pkt2timeout后,重新发送pkt2,以及之后的pkt3,pkt4...统统重发出去。

看一道题:

11.数据链路层采用后退N帧(GBN)协议,发送方已经发送了编号为0~7的帧。当计时器超时时,若发送方只接收到0、2、3号帧的确认,则发送方需要重发的帧数是(C )。

A.2 B.3 C.4 D.5

解析:连续ARQ协议中,接收方一般采用累积确认的方式即接收方对按序到达的最后一个分组发送确认,

题目中收到3的确认帧就代表编号为0、1、2、3的帧已接收,而此时发送方未收到1号帧的确认只能代表确认帧在返回的过程中丢失了,而不代表1号帧未到达接收方。因此需要重传的帧是编号为4、5、6、7的帧。

GBN协议有一定的难度,需要多看几遍,反复琢磨一下。


shijiebei 365bet manbetx 188bet xinshui caipiao 95zz tongbaoyule beplay 88bifa 18luck betway bwin hg0088 aomenjinshayulecheng ca88 shenbotaiyangcheng vwin w88 weide