Leetcode刷题训练第四周

文章目录

数组

  • Leetcode 119: Pascal’s Triangle IIeasy
    • 解题关键:
      • 暴力解法,构造pascal’s triangle, 找到对应rowIndex的行,构造成List
        // 构造pascal's triangle的逻辑, 注意数组长度是rowIndex + 1
        int[][] triangle = new int[rowIndex + 1][rowIndex + 1]
        for (int i = 0; i < rowIndex + 1; i ++) {
          for (int j = 0; j <= i; j ++) {
            if (j == 0 || j == i) { 
              triangle[i][j] = 1;
            } else {
              // 根据pascal's triangle定义
              triangle[i][j] = triangle[i - 1][j - 1] + triangle[i][j - 1];
            }
          }
        }
        
  • Leetcode 915: Partition Array into Disjoint Intervalsmedium
    • 解题关键:
      • 此题最关键的是找到left side的最大值,确保right side中任意一个值都大于该值
      • 同时要找到right side中在数组里index最小的位置
      • 使用 [[贪心算法(Greedy Algorithm)]]
          // 初始化两个最大值,一个是当前left side最大值,一个是用于遍历整个数组的可能出现的下一个最大值
          // 初始化为当前数组第一个值
          int currentMax = nums[0];
          int nextMax = nums[0];
          
          int ret = 0;
          
          // 遍历数组
          for (int i = 1; i < nums.length; i ++) {
            int currentVal = nums[i];
            // 若当前值大于nextMax,则更新nextMax
            nextMax = Math.max(currentVal, nextMax);
            // 若当前值小于当前最大值currentMax,记录下当前索引,并更新左边当前最大值为nextMax
            if (currentVal < currentMax) {
              currentMax = nextMax;
              ret = i;
            }
          }
          // 当前坐标为left side最后一个索引,因此应返回ret + 1
          return ret + 1
        
        

字符串

  • Leetcode 20: Valid Parentheseseasy

    • 解题关键:
      • 1,corner case判断,若字符串为空,则直接返回true
        if (s.length() == 0) return true;
        
      • 2,根据题意,相邻的() [] {}即为valid,可以考虑使用栈结构,后进先出(Last In First Out)原则,匹配到成pair的符号则pop元素,最后合法的字符,栈一定会被清空
        for (char c: s.toCharArray()) {
          // 如果是open状态的符号,则push进栈
          if (c == '(' || c == '[' || c == '{') {
            stack.push(c);
          } else {
            // 若栈此时为空,但还未遍历完,说明下一个char有可能是'}])'中的一个,说明是不合法的,返回false
            if (stack.isEmpty()) {
              return false;
            }
            // 若下一个元素是'}])'中的一个,与当前栈的元素进行比对
            if (c == ']' && stack.peek() != '[') {
                            return false;
                        } else if (c == '}' && stack.peek() != '{') {
                            return false;
                        } else if (c == ')' && stack.peek() != '(') {
                            return false;
                        }
                        // 若未返回false,说明匹配pair成功,从栈里pop该元素
                        stack.pop();
          }
        }
        return stack.isEmpty();
        
  • Leetcode 22: Generate Parenthesesmedium

    • 解题关键:理解[[回溯算法(backtracking)]]
  • Leetcode 67: Add Binaryeasy

    • 解题关键:
      • 理解题意,是将两个字符串的二进制数转化成十进制,相加后再转化为二进制数
      • 需要注意当a, b的二进制非常长的时候,会超出默认类型的长度(int, Integer),因此考虑使用BigInteger类型,或者手写二进制转十进制
            StringBuilder ret = new StringBuilder();
            // index starts from the end
            int aIndex = a.length() - 1;
            int bIndex = b.length() - 1;
            int carry = 0;
            while (aIndex >= 0 || bIndex >= 0) {
                int sum = 0;
                if (aIndex >= 0) {
                    // change char to int
                    sum += a.charAt(aIndex) - '0';
                    aIndex --;
                }
                // the same to string b
                if (bIndex >= 0) {
                    sum += b.charAt(bIndex) - '0';
                    bIndex --;
                }
                sum += carry;
                ret.append(sum % 2);
                carry = sum / 2;
            }
            if (carry > 0) {
                ret.append(carry);
            }
            return ret.reverse().toString();
    
  • Leetcode 443: String Compressionmedium

    • 解题关键
      • 本题使用滑动窗口算法解决
        • 1,corner case判断,若长度为1,直接返回,因为长度为1的字符后面数字不用添加

          int length = chars.length;
          if (length == 1) {
            return length;
          }
          
          
          
        • 2,定义窗口的左右边界

          int left = 0;
          int right = 0;
          // i为遍历索引,便于in-place change,结合题意需要constant extra space
          int i = 0;
          	  
          
        • 3,核心逻辑

          	  // 以窗口右边界为基准
          	  while (right < length) {
          	      // 定义一个计数器,保存每个字符的数量
          	      int count = 0;
          	      // 存储每个窗口的字符
          	      char c = chars[left];
          	      while (right < length && chars[right] == c) {
          	          // 基于窗口右边界进行遍历,计算窗口范围
          	          count ++;
          	          right ++;
          	      }
          	  
          	      // in-place change
          	      chars[i] = c;
          	      // i索引加1,即字符的后一位为计数值
          	      i ++;
          	  
          	      // 若count大于1,则需要在字符后添加数字
          	      if (count > 1) {
          	          // 若计数大于两位数,用for循环将数字转为char array,然后依次更换chars中的位置,同时i递增
          	          for (char character: Integer.toString(count).toCharArray()) {
          	              chars[i] = character;
          	              i ++;
          	          }
          	      }
          	      // 当right遍历到下一个字符时,此时将窗口左边界更新,重新开启一个新窗口计算下一组字符
          	      left = right;
          	  }
          	  // 返回最后的i
          	  return i;
          
          
  • Leetcode 791: Custom Sort Stringmedium

    • 解题思路
      • 根据题意,因为待排序的的字符长度最大为200,而元素范围是26个英文字母,基于该特性可以使用计数排序算法

        	// 创建一个长度为26的数组存储排序字符计数
        	int[] tmp = new int[26];
        	for (char c: str.toCharArray()) {
        	    // 根据char - 'a'获得在tmp数组中的索引位置,同时计数
        	    tmp[c - 'a'] ++;
        	}
        	// 例如str为"abcddd",那么tmp此时为
        // [1, 1, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        
        
        
      • 由于排序规则是根据给定的字符来指定,因此基于排序规则的字符在tmp数组中找到对应位置,并计算该字符数量进行递减

        for (char c: order.toCharArray()) {
            while (tmp[c - 'a'] > 0) {
                sb.append(c);
            }
        }
        
      • 其余字符根据字母顺序排序插入StringBuilder即可

        for (int i = 0; i < 26; i ++) {
            while (tmp[i] -- > 0) {
                sb.append((char) (i + 'a'));
            }
        }
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值