小白算法刷题Day4

  • 最大正方形:思路是利用动态规划求解。遍历所有可能的长度,把矩阵中的每个点都当成这个长度下的正方形的右下角,判断当前长度下以这个点为右下角的正方形是否存在,存在DP[i][j]等于面积。判断的条件是确定这个点的上方,左方,左上方的值不小于上一轮的lenth*length。加入一个ans 每次找到更大的面积就更新ans。最后返回ans便是答案。
  • class Solution {
        public int maximalSquare(char[][] matrix) {
            int maxLength = matrix.length > matrix[0].length ? matrix[0].length : matrix.length;
            int[][] DP = new int[matrix.length][matrix[0].length];
            int ans = 0;
            for(int i = 0; i < matrix.length; i++){
                for(int j = 0; j < matrix[0].length; j++){
                    if(matrix[i][j] == '0'){
                        DP[i][j] = 0;
                    }else{
                        DP[i][j] = 1;
                        ans = 1; 
                    }
                }
            }
            for(int length = 2; length <= maxLength; length++){
                int lastArea = (length - 1) * (length - 1);
                for(int i = length - 1; i < matrix.length; i++){
                    for(int j = length - 1; j < matrix[0].length; j++){
                        if(DP[i - 1][j] >= lastArea && DP[i][j - 1] >= lastArea && DP[i - 1][j - 1] >= lastArea && DP[i][j] > 0){
                            DP[i][j] = length*length;
                            ans = DP[i][j] > ans ? DP[i][j] : ans;
                        }
                    }
                }
            }
            return ans;
        }
    }

  • 字符串解码:遍历字符串,在没遇到 ']' 之前所有字符变成字符串依次入栈,遇到 ']' 之后开始栈,直到遇到了' [ ',把刚才出栈的字符加起来。(对于字符串来说 s1 + s2 与s2 + s1 的结果是不一样的),再多弹出一个因为当前栈顶是'[', 继续出栈直到栈顶元素不是 0 - 9 的数字或栈空了,把这一块需要重复的次数找出来。也是通过栈顶元素相加 因为是string类所以都需要注意顺序。 生成新的字符串之后再压入栈中,继续往下走。得到结果
  • class Solution {
        public String decodeString(String s) {
            Stack<String> stack = new Stack<String>();
            for(int i = 0; i < s.length(); i++){
                char ch = s.charAt(i);
                if(ch == ']'){
                    String str = "";
                    while(!stack.peek().equals("[")){
                        str = stack.pop() + str;
                    }
                    stack.pop();
    
                    String repeatString = "";
                    while(!stack.isEmpty() && (stack.peek().charAt(0) >= '0' && stack.peek().charAt(0) <= '9')){
                        repeatString = stack.pop()+ repeatString;
                    }
                    int repeatTimes = Integer.parseInt(repeatString);
    
                    String partAns = "";
                    for(int j = 0; j < repeatTimes; j++){
                        partAns = partAns + str;
                    }
                    stack.push(partAns);
                }else{
                    stack.push(ch + "");
                }
            }
            
            String ans = "";
            while(!stack.isEmpty()){
                ans = stack.pop() + ans;
            }
            return ans;
        }
    }


  • 森林中的兔子:将兔子的答案排序一下 Arrays.sort(answers); (方法名不要再记错了) 遍历数组,0意味着至少有一只这样的兔子,所以所有的0都使最后答案加1. 之后往后找和当前位置相同的数字有多少个这些些有相同答案的兔子可以当成一类,但是相同数字的个数不能操作当前数字 + 1。一只往后找直到没有兔子。需要注意的是如果最后一只兔子不属于任何一类答案还需要加上最后一子兔子的答案+1;
  • class Solution {
        public int numRabbits(int[] answers) {
            Arrays.sort(answers);
            int sameRabit = 0;
            int ans = 0;
            for(int i = 0; i < answers.length; i++){
                for(int j = i + 1; j < answers.length; j++){
                    if(answers[j] == answers[i] && answers[j] != 0 && sameRabit < answers[i]){
                        sameRabit++;
                    }else{
                        ans += answers[i] + 1;
                        i += sameRabit;
                        sameRabit = 0;
                        break;
                    }
                }
                if(i == answers.length - 1){
                    ans += answers[i] + 1;
                }
            }
            return ans;
        }
    }

  •  三数之和:给一个包含n个整数的数组,判断里面是否有三个数加起来等于0;找出所有和为1的不重复三元组。 首先将数组进行排列,Arrays.sort(arr); 用全排列的思想,找出所有组合判断合适否为0,又与全排列不完全相同, 因为同样三数字在不同位置的组合没有意义,所以不需要数组来标记某个数是否被访问过。我们只需要让程序在寻找下一个数的时候从当前位置开始找就行了。最后超出时间限制了,想了几种办法来限制无用组合的产生,第一种是,当选取的第一二个数加上数组尾部的数仍然小于0时就不必再往下递归了。第二种是,当选取的第一个数比加上尾部两个数的和仍让小与0时也不必往下递归了。 这样优化仍然超出时间限制。 以后再来完善。在这里存储结果的数据结构用的是HashSet, 因为是经过排序的数组 所以生成可添加的结果时如果不会出现(1,1,-2)和(-2,1,1)这种情况,我们只需考虑数组中有三个连续的1的情况。
  • Java HashSet的遍历可以使用加强for循环 for( (类型) item : set)。。
  • class Solution {
        public List<List<Integer>> threeSum(int[] nums) {
            List<List<Integer>> ansReal = new ArrayList<List<Integer>>();
            List<Integer> possibleAns = new ArrayList<Integer>();
            HashSet<List<Integer>> ans = new HashSet<List<Integer>>();
            Arrays.sort(nums);
            backTrack(ans, possibleAns, 0, nums, 0);
            for(List item : ans){
                ansReal.add(item);
            }
            return ansReal;
        }
        public void backTrack(HashSet<List<Integer>> ans, List<Integer> possibleAns, int curStep, int[] numsReal, int starPos){
            if(curStep == 3){
                int sum = 0;
                for(int i = 0; i < possibleAns.size(); i++){
                    sum += possibleAns.get(i);
                }
                if(sum == 0 && possibleAns.size() == 3){
                    ans.add(new ArrayList<Integer>(possibleAns));
                }
                return;
            }else{
                for(int i = starPos; i < numsReal.length; i++){
                    possibleAns.add(numsReal[i]);
                    if(possibleAns.size() == 1 && numsReal.length > 2){
                        if(possibleAns.get(0) + numsReal[numsReal.length - 2] + numsReal[numsReal.length - 1] < 0){
                            possibleAns.remove(possibleAns.size() - 1);
                            continue;
                        } 
                    }
                    if(possibleAns.size() == 2){
                        if(possibleAns.get(0) + possibleAns.get(1) + numsReal[numsReal.length - 1] < 0){
                            possibleAns.remove(possibleAns.size() - 1);
                            continue;
                        } 
                    }
                    backTrack(ans, possibleAns, curStep + 1, numsReal, i + 1);
                    possibleAns.remove(possibleAns.size() - 1);
                }
            }
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值