Day04_剑指Offer

Day04_剑指Offer

得到一点小启发,顺序的就会想到二分 树的就想到递归 倒序的就想到栈。

通过每天做做题,第二天重新思考前一天学的算法题,每天都有进步。加油

分享一句话:路都是一步一个脚印走出来的,没有人可以突然暴富,只有厚积薄发才能走得更远。加油!!

今天的三道题都用到二分法

package com.sorrymaker.day2804;

import org.junit.Test;

/**
 * 找出一个长度为n数组nums里面的 重复数字,只要重复了就拿出来。
 *
 * 在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。
 * 数组中某些数字是重复的,但不知道有几个数字重复了,
 * 也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
 * @Author nextGame
 * @Date 2021/8/15 15:32
 * @Version 1.0
 */
public class findRepeatNumber {


    @Test
    public void test(){
        int[] nums ={3, 4, 2, 1, 0, 1};
        System.out.println(findRepeatNumber(nums));
    }

    public int findRepeatNumber(int[] nums) {
        //这个是索引,从0,开始
        int i = 0;
        while(i < nums.length) {
            //假如数组中的数据nums[i] == i ; 即是nums[1] = 1的时候
            if(nums[i] == i) {
                //索引加1,继续遍历循环。因为true的话,说明,现在的索引和对应的值是对应的。
                i++;
                continue;
            }
            //这里就要拆封一下了。我们首先来看,
            //当nums[i] = i ; nums[num[i]] ==>> nums[i]  == nums[i]这里就会成立。
            //为什么这里会返回呢?因为我们上面的if语句已经判断过了,假如索引 == num[i] ,我们就会i++,并继续循环。
            // 即是出现重复的值,我们就返回这个值出来。
            //因为索引是从0开始的
            if(nums[nums[i]] == nums[i]) {
                return nums[i];
            }

            //这里下面就是帮助我们排序数组把,把

            //存放nums数组 的 i索引的数字。
            int tmp = nums[i];
            //将nums索引位temp 的数值 赋值给 nums 索引为 i的 。
            nums[i] = nums[tmp];
            //这里就是把对应位置的num[tmp] = tmp
            nums[tmp] = tmp;
        }
        return -1;
    }
}


    /**
     *        太慢太垃圾了,更新一个又快又猛的。
     *         int count=0;
     *         for (int i = 0; i < nums.length; i++) {
     *             for (int j = i+1;j<nums.length;j++){
     *                 if(nums[i] == nums[j]){
     *                     return count = nums[j];
     *                 }
     *
     *             }
     *         }
     *         return count;
  
  */

https://pic.leetcode-cn.com/45a6303cd3ab50036a99ae89e2b0458f9b4885bb9d089997dfc0e5851a6a6300-Picture7.png

package com.sorrymaker.day2804;


/**
 * 排序数组中的搜索问题,首先想到 二分法 解决
 * @Author nextGame
 * @Date 2021/8/15 17:28
 * @Version 1.0
 */
public class MissingNumber {

    public int missingNumber(int[] nums) {
        //左边界 i ,右边界 j
        int i = 0, j = nums.length - 1;
        while (i <= j) {
            //二分法
            int m = (i + j) / 2;
            if (nums[m] == m) {
                i = m + 1;
            } else {
                j = m - 1;
            }
        }
        return i;
    }
}

https://pic.leetcode-cn.com/515ad046b4363de9324acc0ce74d9fa9048d5526c66a91539b99c26fbe4a49cb-Picture2.png

package com.sorrymaker.day2804;

import org.junit.Test;

/**
 * 排序数组记得用二分法,记得用二分法,记得,记得噢噢噢噢
 * 二分法,就是找到想要找到的数字的左边和右边,右边-左边-1就是target出现的频率了。
 * 这道题用的是优化的二分法,由于是排序数组,只需要找到有边界,和target-1的右边界,就是出现的次数了。
 * 例如 target = 8, target-1 = 7 。  target的右边界为9,target-1 的有边界为8,
 * 然后重复次数 =  target右边界 - target-1的右边界 。
 * @Author nextGame
 * @Date 2021/8/15 16:42
 * @Version 1.0
 */
public class Search {

    @Test
    public void test() {
        int[] nums = {10, 11, 12, 13, 14, 15};
        int target = 10;
        System.out.println(search(nums, target));
    }

    public int search(int[] nums, int target) {
        return count(nums,target)-count(nums,target-1);
    }

    int count(int[] nums, int target) {
        //i 和 j分别是数组的起始索引和结尾索引。
        int i = 0, j = nums.length - 1;
        //这里的i和j分别是左右边界,左边始终小于等于右边
        while(i <= j) {
            // 二分得到的值。
            int m = (i + j) / 2;
            //当数组在m索引的值 <=目标值,说明,左边还可以在缩小一格,即i= m+1
            if(nums[m] <= target) {
                i = m + 1;
            } else {
            //当出先数组在m索引的值 >目标值,说明,右边可以在缩小一点,即j=m-1。
                j = m - 1;
            }
        }
        return i;
    }

}

/**
 * 弱智写法
 * int count=0;
 * for(int n:nums){
 * if(n==target){
 * count++;
 * }
 * }
 * return count;
 * }
 */
上一篇:day04


下一篇:React_day04_react路由、组件间通信、新闻网站构建