Leetcode刷题训练第三周

二分法

数组

  • Leetcode 605: Can Place Flowerseasy

    • 解题关键
      • corner case处理

          	  	  if (n == 0) {
          	  	      return true;
          	  	  }
          	  	  int length = flowerbed.length;
          	  	  if (length == 1) {
          	  	      return flowerbed[0] == 0;
          	  	  }
        
      • 找到符合条件数组中0的位置

          	  	  if (i == 0) {
          	  	  		// handle the start
          	  	      if (flowerbed[i + 1] == 0) {
          	  	          ret ++;
          	  	          flowerbed[0] = 1;
          	  	      }
          	  	  // handle the end
          	  	  } else if (i == length - 1) {
          	  	      if (flowerbed[length - 2] == 0) {
          	  	          ret ++;
          	  	          flowerbed[length - 1] = 1;
          	  	      }
          	  	  } else if (flowerbed[i - 1] == 0 && flowerbed[i + 1] == 0) {
          	  	      ret ++;
          	  	      flowerbed[i] = 1;
          	  	  }
        
  • Leetcode 189: Rotate Arraymedium

    • 解题关键
      • 1,corner case 判断

        • 当数组长度=0或=1,直接返回

            		  int length = nums.length;
            		  if (length == 0 || length == 1) {
            		    return nums;
            		  }
          
        • 2,若k大于或等于数组长度的情况,实际代表旋转后又重新回到初始状态,因此需要对k取模,只排序取模后的长度

            		  k %= length
          
      • 2,交换索引位置的区间元素

        • 1,交换方法

            		  private void swap(int[] nums, int left, int right) {
            		    int tmp;
            		    while (left < right) {
            		      tmp = nums[left];
            		      nums[left] = nums[right];
            		      nums[right] = tmp;
            		      left ++;
            		      right --;
            		    }
            		  }
          
        • 2,注意交换的索引位置

            		  swap(nums, 0, length - 1);   // 先旋转整个数组
            		  swap(nums, 0, k - 1);    // 再旋转从0到k - 1处的元素
            		  swap(nums, k, length - 1);    // 再旋转从k到length - 1处的元素
            		  /**
            		  [1,2,3,4,5,6,7] k = 3
            		  第一次交换:[7,6,5,4,3,2,1]
            		  第二次交换:[5,6,7,4,3,2,1]
            		  第三次交换:[5,6,7,1,2,3,4]
            		  **/
          
  • Leetcode 229: Majority Element IImedium

    • 解题关键

贪心算法(Greedy Algorithm)

  • Leetcode 122: Best Time to Buy and Sell Stock IIeasy

    • 解题关键:
      • 1, corner case 判断

        	// 若数组长度小于2,那么无论是sell或者是buy,都不会有收益
        	  if (prices.length < 2) {
        	    return 0;
        	  }
        
      • 2, 计算每一次sell和buy过程获得的收益进行叠加,从而得到最大收益

        	 // 索引从1开始,便于与i - 1进行比较
        	  for (int i = 1; i < prices.length; i ++) {
        	    // 只有当前值大于前一天的值,说明sell才会获得收益
        	    if (prices[i] > prices[i - 1]) {
        	      ret += prices[i] - prices[i - 1]
        	    }
        	  }
        
  • Leetcode 455: Assign Cookieseasy

    • 解题关键:
      • 1, corner case 判断

        	 // 若s长度为0,则满足不了任何孩子,因此可直接返回0
        	  if (s.length == 0) return 0;
        	  // 但由于我们使用贪心算法,遍历两个数组时,需要索引条件同时成立,因此也可不做此判断
        
      • 2, 考虑到孩子的贪心度是第i个孩子为g[i],因此可以对两个数组先进行排序

        	  Arrays.sort(g);
        	  Arrays.sort(s);
        
      • 3, 同时遍历两个数组,当g[i]小于或等于s[j]时,说明可以满足当前孩子,则叠加返回值,需要注意的是索引j为s的最小值,若该值满足当前孩子,说明后面的同样满足,因此只有在g[i]大于s[j]时,才将j进行叠加

        	  while (i < g.length && j < s.length) {
        	    if (g[i] <= s[j]) {
        	      ret ++;
        	      i ++;
        	    }
        	    j ++;
        	  }
        
  • Leetcode 921: Minimum Add to Make Parentheses Validmedium

    • 解题关键:
      • 1,corner case判断

          // 考虑到字符串有可能为空,因此当字符串为空时直接返回0 
          if (s.length() == 0) return 0;
        
      • 2,遍历字符串,定义open(’(’)计数,初始化为0,计数逻辑为:

        • 当字符为’('时,open加1
        • 当字符为’)'时
          • 先判断open是否为0,若为0,说明前面的’(‘与’)'已经抵消,因此需要增加补充的数量(ret)加1

          • 若open不为0,那么优先与open抵消,即open减1

              for (int i = 0; i < s.length(); i ++) {
                if (s.charAt(i) == '(') {
                  open ++;
                } else {
                  if (open == 0) {
                    ret ++;
                  } else {
                    open --;
                  }
                }
              }
            
      • 3,最后返回值为open+ret总数

          return ret + open;
        
  • Leetcode 714: Best Time to Buy and Sell Stock with Transaction Feemedium

    • 解题关键:
      • 1,corner case判断

          // 当数组长度小于2时,此时没有任何收益,直接返回0
          if (length < 2) return 0;
        
      • 2,定义需要的一些变量

          int[] dp = new int[length];    // 存储遍历数组时所有可能的收益
          int maxProfit = 0;    // 初始化最大收益
          int prevProfit = 0;    // 初始化遍历数组时当前索引之前的收益
          int minPrice = prices[0];    // 初始化最小价格为当前数组第一个值
        
      • 3,遍历数组

         for (int i = 1; i < length; i ++) {
            dp[i] = prices[i] - minPrice - fee + prevProfit;  // 每次遍历取得的收益存进dp数组
            if (prevProfit - minPrice < maxProfit - prices[i]) {    // 若之前的收益减去当前最小价格小于最大收益减去当前价格,说明之前的收益不是最大化的
              prevProfit = maxProfit;    // 更新之前的收益为最大收益
              minPrice = prices[i];    // 更新最小价格为当前价格
            }
            maxProfit = Math.max(maxProfit, dp[i]);    // 更新最大收益
          }
        
  • Leetcode 435: Non-overlapping Intervalsmedium

    • 解题关键:
      • 1,corner case判断

          // 若二维数组长度为1,说明只有一个区间,因此没有任何可以去掉的多余区间,直接返回0
          if (length < 2) return 0;
        
      • 2,由于是去掉会重叠的区间,最后得到不重叠的区间,因此需要考虑区间的判断逻辑

        • 当intervals[i][0]大于等于intervals[i - 1][1]时,两个区间可认为不重叠
    		// 先将二维数组进行排序,以子数组中第一个元素大小为基准
    	  Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
    	  // 定义一个缓存数组,存储当前区间范围,便于二维数组时子数组的区间判断
    	  int[] tmp = new int[2];
    	  tmp[0] = Integer.MIN_VALUE;
    	  tmp[1] = Integer.MIN_VALUE;
    	  // 遍历二维数组
    	  for (int i = 0; i < intervals.length; i ++) {
    	    // 当前区间范围为tmp,因此如果tmp[1]大于intervals[i][0]时,说明会有重叠,需要去掉
    	    if (tmp[1] > intervals[i][0]) {
    	      ret ++;
    	      // 考虑到不重叠的情况,当前区间的end应该取较小值
    	      tmp[1] = Math.min(tmp[1], intervals[i][1]);
    	    } else {
    	      // 若tmp[1]小于等于intervals[i][0],说明两个区间不重叠,由于数组已经经过排序,因此当前区间变为intervals[i],继续进行比较
    	      tmp = intervals[i];
    	    }
    	  }
    					  				  
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值