B站左程云算法视频中级班04

题目一:洗衣机问题

第一步:先看sum%N

第二步:看第i台机器

一)左右都是负,至少 |左| + |右|

二)左右都是正,至少 max(|左|,|右|)

三)左负右正 ,至少max(|左|,|右|)

四)左正右负,至少max(|左|,|右|)

每个点算出答案,最痛的点就是瓶颈

public int findMinMoves(int[] machines) {
        if(machines.length < 1 || machines == null){
            return -1;
        }
        int sum = 0;
        int N = machines.length;
        for(int i = 0; i < machines.length;i++){
            sum += machines[i];
        }
        if(sum % N != 0){
            return -1;
        }
        int avg = sum/N;
        int leftSum = 0;
        int ans = 0;
        for(int i = 0; i < machines.length;i++){
            int leftRest = leftSum - i * avg;
            int rightRest = (sum - leftSum - machines[i]) - (machines.length - i - 1) * avg;
            if(leftRest < 0 && rightRest < 0 ){
                ans = Math.max(ans, Math.abs(leftRest)+Math.abs(rightRest));
            }else{
                ans = Math.max(ans, Math.max(Math.abs(leftRest),Math.abs(rightRest)));
            }
            leftSum += machines[i];
        }
        return ans;
    }

题目二:(宏观调度)

螺旋的方式打印矩阵

0 1 2 3

4 5 6 7

8 9 10 11

打印顺序 0  1  2  3  7  11  10  9  8  4  5  6 

给一个左上角和右下角,实现函数 只打印这个框

public static void spiralOrderPrint(int[][] matrix){
    int tR = 0;
    int tc = 0;
    int dR = matrix.length - 1;
    int dC = matrix[0].length - 1;
    while(tR <= dR && tC <= dC){
        printEdge(matrix, tR++, tC++, dR--, dC--);
    }
}


public static void printEdge(int[][] m, int a, int b, int c, int d){
    if(a == c){
        for(int i = b; i <= d; i++){
            System.out.print(m[a][i] + " ");
        }//横线
    }else if(b == d){
        for(int i = a; i <= c; i++){
            System.out.print(m[i][b] + " ");
        }//竖线
    }else {
        int curC = b;
        int curR = a;
        while(curC != d){
            System.out.print(m[a][curC] + " ");
            curC++;
        }//往右
        while(curR != c){
            System.out.print(m[curR][d] + " ");
            curR++;
        }//往下
        while(curC != b){
            System.out.print(m[c][curC] + " ");
            curC--;
        }//往左
         while(curR != a){
            System.out.print(m[curR][b] + " ");
            curR--;
        }//往上
    }
}

 给定一个正方形矩阵,只用有限几个变量,实现矩阵中每个位置的数顺时针转动90度,比如下面的矩阵

 0        1        2        3

 4        5        6        7

 8        9       10      11

12      13      14      15

调整为

12        8        4        0

13        9        5        1

14       10       6        2

15       11       7        3       

先处理

0     1      2      3

4                     7

8                    11

12  13    14    15

分成三组

0                   3                 1                                           2

                                                        7          4

                                8                                                          11

12               15                         14                      13

三组

假设现在的框左上角 a行b列 右下角  c行d列,共有d-b+1组  

第一个for循环,规定有几组

第i组的第一个第二个第三个和第四个

1) m[a][b+i]

2)   m[a+i][d]

3)   m[c][d-i]

4)   m[c-i][b]

public static void rotate(int[][] matrix){
    int tR = 0;
    int iC = 0;
    int dR = matrix.length - 1;
    int dC = matrix[0].length - 1;
    while(tR < dR){
        rotateEdge(matirx, tR++, tC++, dR--, dC--);
    } 
}

public static void rotateEdge(int[][] m, int a, int b, int c, int d){
    int times = d - b;
    int tmp = 0;
    for (int i = 0; i != times; i++){
        tmp = m[a][b + i];
        m[a][b + i] = m[c - i][b];
        m[c - i][b] = m[c][d - i];
        m[c][d - i] = m[a + i][d];
        m[a + i][d] = tmp;
    }
}

Zigzag打印矩阵

public static void printMatrixZigzag(int[][] matrix){
    int ar = 0;
    int ac = 0;
    int br = 0;
    int bc = 0;
    int endR = matrix.length - 1;
    int endC = matrix[0].length - 1;
    while(ar != endR + 1){
        printLevel(matrix, ar, ac, br, bc, fromUp);
        ar = ac == endC ? ar + 1 : ar;
        ac = ac == endC ? ac : ac + 1;
        bc = br == endR ? bc + 1 : bc;
        br = br == endR ? br : br + 1;
        fromUp = !fromUp; 
    }
    System.out.println();
}

public static void printLevel(int[][] m, int tR, int tC, int dR, int dC, boolean f){
    if(f){
        while(tR != dR + 1){
            System.out.print(m[tR++][tc--] + " ");
        }
    }else{
        while(dR != tR - 1){
            System.out.print(m[dR--][dC++] + " ");
        }
    }

}

题目三:假设s和m初始化, s = "a" ; m = s

再定义两种操作,第一种:

m = s;

 s = s + s;

第二种操作:

s = s + m;

求最小的操作步骤数,可以将s拼接到长度等于n

如果n是质数,只调用操作二达到的步骤数是最少步骤数

操作1是有因子的

n不是质数,假设n由某些质数因子构成,假设一个最优顺序n = x* y * z* p

搞定x * y * z 之后 ,调用p -1 次操作二

所以是x+y+z+p-4

//请保证n不是质数
//返回:
//0) 所有因子的和,但是因子不包括1
//1) 所有因子的个数,但是因子不包括1
public static int[] divsSumAndCount(int n){
    int sum = 0;
    int count = 0;
    for(int i = 2; i <= n; i++){
        while(n % i == 0){
            sum += i;
            conut++;
            n /= i;
        }
    }
    return new int[] {sum, count};
}

public static int minOps(int n) {
    if (n < 2){
        return 0;
    }
    if (isPrim(n)){
        return n - 1;
    }
    //n不是质数
    int[] divSumAndCount = divsSumAndCount(n);
    return divSumAndCount[0] - divSumAndCount[1];
}

题目四:给一个数组,出现次数前K的字符串

词频表(key字符串,value词频)

堆(大根堆/小根堆(门槛))

扩展:设计结构,这个结构可以接受用户给的字符串add(str),且可以随时显示目前排名前k的字符串void printTopK()(动态结构)

思路:改堆

词频表(key 字符串, value 词频)

堆[初始k个长度] heapsize = 0;

记录某个字符串在堆上的位置 map(key 字符串 , value 位置)

public static class Node{
    public String str;
    public int times;

    public Node(String s, int t){
        public String str;
        public int times;

        public Node(String s, int t){
            str = s;
            times = t;
        }
    }

    public static class TopKRecord{
        private HashMap<String, Node> strNodeMap;
        private Node[] heap;
        private int index;

        private HashMap<Node, Integer> nodeIndexMap;
        
        public TopKRecord(int size){
            heap = new Node[size];
            index = 0;
            strNodeMap = new HashMap<String, Node>();
            nodeIndexMap = new HashMap<Node, Integer>();
        }
        
        public void add(String str){
            //当前str对应的节点对象
            Node curNode = null;
            //当前str对应的节点对象是否在堆上
            int preIndex = -1;
            if (!strNodeMap.containsKey(str)){//第一次出现
                curNode = new Node(str, 1);
                strNodeMap.put(str, curNode);
                nodeIndexMap.put(curNode, -1);
            }else{ // 并非第一次出现
                curNode = strNodemap.get(str);
                curNode.times++;
                preIndex = nodeIndexMap.get(curNode);
            }

            
            if (preIndex == -1){//当前str对应的节点对象,词频增加后不在堆上
                if(index == heap.length){
                    if(heap[0].times < curNode.times){
                        nodeIndexMap.put(heap[0], -1);
                        nodeIndexMap.put(curNode, 0);
                        heap[0] = curNode;
                        heapify(0, index);
                    }
                } else {
                    nodeIndexMap.put(curNode, index);
                    heap[index] = curNode;
                    heapInsert(index++);
                }
            }else {
                    heapify(preIndex, index);
                }
        }
    
        public void printTopK(){
            System.out.println("TOP: ");
            for (int i = 0; i != heap.length; i++){
                if(heap[i] == null){
                    break;
                }
                System.out.print("Str: " + heap[i].str);
                Ststem.out.prinln("Times: " + heap[i].times);
            }
        }
        
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值