左程云大厂算法刷题班——07

第一题

leetcode42:接雨水

public class 第一题01 {
    public static int trap1(int[] height) {
        int n = height.length;
        int sum = 0;
        int[] left = new int[n];
        int[] right = new int[n];
        left[0] = height[0];
        for (int i = 1;i < n;i++){
            left[i] = Math.max(left[i -  1],height[i]);
        }
        right[n - 1] = height[n - 1];
        for(int i = n - 2;i >= 0;i--){
            right[i] = Math.max(right[i + 1],height[i]);
        }
        for (int i = 1;i < n - 1;i++){
            int min_height = Math.min(left[i],right[i]);
            sum += min_height > height[i] ? min_height - height[i] : 0;
        }
        return sum;
    }
    public static int trap2(int[] height) {
        int left_max = 0;
        int right_max = 0;
        int l = 0;
        int r = height.length - 1;
        int sum = 0;
        while (l < r){
            if (left_max > right_max){
                sum += right_max > height[r] ? right_max - height[r] : 0;
                right_max = Math.max(right_max,height[r]);
                r--;
            }else {
                sum += left_max > height[l] ? left_max - height[l] : 0;
                left_max = Math.max(left_max,height[l]);
                l++;
            }
        }
        return sum;
    }
}

第二题

在这里插入图片描述
leetcode169:多数元素
1.超级水王问题:给你一个数组,出现次数大于数组长度的一半的元素称之为水王数,怎么能快速找到水王数?
内存限制:时间复杂度O(n),额外空间复杂度O(1)——也就是遍历数组的次数为有限次,申请的变量数为有限个
2.扩展:给定一个长度为N的数组arr,和一个大于1的正整数K,如果有哪些数出现的次数大于N/K,就返回这些数
要求:时间复杂度O(N) 额外空间复杂度O(K)

public class 第二题07 {
    public static void main(String[] args) {
        int[] arr = {1,2,3,1,2,3,1,2,1,2,1,2,1,3};
        int res = waterKing(arr);
        System.out.println(res);
        List<Integer> list = getSuperWaterExtension(arr, 4);
        System.out.println(list);
    }
    //1.超级水王问题
    public static int waterKing(int[] arr){
        int n = arr.length;
        int cand = 0;
        int hp = 0;
        for (int i = 0;i < n;i++){
            if (hp == 0){
                cand = arr[i];
                hp++;
            }else {
                if (cand == arr[i]){
                    hp++;
                }else {
                    hp--;
                }
            }
        }
        if (hp == 0){
            return -1;
        }
        int mid = n / 2;
        int num = 0;
        for (int i = 0;i < n;i++){
            if (cand == arr[i]){
                num++;
            }
        }
        if (num > mid){
            return cand;
        }
        return -1;
    }
    //2.扩展:给定一个长度为N的数组arr,和一个大于1的正整数K,如果有哪些数出现的次数大于N/K,就返回这些数(时间复杂度O(N) 额外空间复杂度O(K))
    public static List<Integer> getSuperWaterExtension(int[] arr, int K){
        HashMap<Integer, Integer> map = new HashMap<>();
        int n = arr.length;
        for (int i = 0;i < n;i++){
            if (map.containsKey(arr[i])){
                map.put(arr[i],map.get(arr[i]) + 1);
            }else {
                if (map.size() == K - 1){
                    allMapMinusOne(map);
                }else {
                    map.put(arr[i],1);
                }
            }
        }
        HashMap<Integer,Integer> res = getReals(arr,map);
        ArrayList<Integer> ans = new ArrayList<>();
        int M = n / K;
        for (Integer num : res.keySet()){
            if (res.get(num) > M){
                ans.add(num);
            }
        }
        return ans;
    }

    private static HashMap<Integer, Integer> getReals(int[] arr, HashMap<Integer, Integer> map) {
        HashMap<Integer, Integer> res = new HashMap<>();
        for (int num : arr){
            if (map.containsKey(num)){
                res.put(num,res.getOrDefault(num,0) + 1);
            }
        }
        return res;
    }

    private static void allMapMinusOne(HashMap<Integer, Integer> map) {
        ArrayList<Integer> list = new ArrayList<>();
        for (Integer num : map.keySet()){
            Integer count = map.get(num) - 1;
            if (count == 0){
                list.add(num);
            }else {
                map.put(num,count);
            }
        }
        for (Integer num : list){
            map.remove(num);
        }
    }
}

第三题

leetcode1000. 合并石头的最低成本
思路:暴力递归——》记忆化搜索

package 高频算法题82.大厂面试算法题.第七天;

    public class 第三题07 {
        //暴力递归
        public static int mergeStones1(int[] stones, int k) {
            int n = stones.length;
            if ((n - 1) % (k - 1) > 0){
                return -1;
            }
            int[] preSum = new int[n + 1];
            for (int i = 0;i < n;i++){
                preSum[i + 1] = preSum[i] + stones[i];
            }
            return process1(stones,0,stones.length - 1,k,1,preSum);
        }
        // [L ... R]合并为part份的最小代价,如果无法完成,返回-1
        // preSum[i]:[0 ... i-1]的前缀累加和
        public static int process1(int[] arr,int L,int R,int K,int P,int[] preSum){
            if (L == R){
                return P == 1 ? 0 : -1;
            }
            if (P == 1){
                int next = process1(arr,L,R,K,K,preSum);
                if (next == -1){
                    return -1;
                }else {
                    return next + preSum[R + 1] - preSum[L];
                }
            }else {
                int ans = Integer.MAX_VALUE;
                for (int i = L;i < R;i += K - 1){
                    int left = process1(arr,L,i,K,1,preSum);
                    int right = process1(arr,i + 1,R,K,P - 1,preSum);
                    if (left != -1 && right != -1){
                        ans = Math.min(ans,left + right);
                    }
                }
                return ans;
            }
        }
        //记忆化搜索
        public static int mergeStones2(int[] stones, int k) {
            int n = stones.length;
            if ((n - 1) % (k - 1) > 0){
                return -1;
            }
            int[] preSum = new int[n + 1];
            for (int i = 0;i < n;i++){
                preSum[i + 1] = preSum[i] + stones[i];
            }
            int[][][] dp = new int[n][n][k - 1];
            return process1(stones,0,stones.length - 1,k,1,preSum,dp);
        }
        public static int process1(int[] arr, int L, int R, int K, int P, int[] preSum, int[][][] dp){
            if (dp[L][R][P] != 0){
                return dp[L][R][P];
            }
            if (L == R){
                return P == 1 ? 0 : -1;
            }
            if (P == 1){
                int next = process1(arr,L,R,K,K,preSum, dp);
                if (next == -1){
                    dp[L][R][P] = -1;
                    return dp[L][R][P];
                }else {
                    dp[L][R][P] = next + preSum[R + 1] - preSum[L];
                    return dp[L][R][P];
                }
            }else {
                int ans = Integer.MAX_VALUE;
                for (int i = L;i < R;i += K - 1){
                    int left = process1(arr,L,i,K,1,preSum, dp);
                    int right = process1(arr,i + 1,R,K,P - 1,preSum, dp);
                    if (left != -1 && right != -1){
                        ans = Math.min(ans,left + right);
                        dp[L][R][P] = ans;
                    }else {
                        dp[L][R][P] = -1;
                    }
                }
                return dp[L][R][P];
            }
        }
    }

第四题

leetcode:剑指 Offer II 017. 含有所有字符的最短字符串

public class 第五题07 {
    public static String removeDuplicateLetters(String s) {
        if (s == null || s.length() < 2){
            return s;
        }
        int[] map = new int[256];
        int n = s.length();
        char[] str = s.toCharArray();
        int ascii_min = 0;
        for (int i = 0;i < n;i++){
            map[str[i]]++;
        }
        for (int i = 0;i < n;i++){
            ascii_min = str[ascii_min] > str[i] ? i : ascii_min;
            map[str[i]]--;
            if (map[str[i]] == 0){
                break;
            }
        }
        return String.valueOf(str[ascii_min]) + removeDuplicateLetters(s.substring(ascii_min + 1).replaceAll(String.valueOf(str[ascii_min]),""));
    }
}

第六题

leetcode22:括号生成

public class 第六题07 {
    public static void main(String[] args) {
        boolean res = isValid("()");
        System.out.println(res);
    }
    public static boolean isValid(String s) {
        int n = s.length();
        char[] str = s.toCharArray();
        char[] stack = new char[n];
        int index = 0;
        for (int i = 0;i < n;i++){
            if (str[i] == '('){
                stack[index++] = ')';
            }else if (str[i] == '{'){
                stack[index++] = '}';
            }else if (str[i] == '['){
                stack[index++] = ']';
            }else {
                if (index <= 0 || stack[--index] != str[i]){
                    return false;
                }
            }
        }
        if (index > 0){
            return false;
        }
        return true;
    }
}

第七题

leetcode36:有效数独

public class 第七题07 {
    public boolean isValidSudoku(char[][] board) {
        boolean[][] row = new boolean[10][10];
        boolean[][] col = new boolean[10][10];
        boolean[][] box = new boolean[10][10];
        for (int i = 0;i < 9;i++){
            for (int j = 0;j < 9;j++){
                if (board[i][j] != '.'){
                    int num = board[i][j] - '0';
                    int b = 3 * (i / 3) + (j / 3);
                    if (row[i][num] || col[j][num] || box[b][num]){
                        return false;
                    }
                    row[i][num] = true;
                    col[j][num] = true;
                    box[b][num] = true;
                }
            }
        }
        return true;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值