【刷题宝典NO.3】

杨辉三角

在屏幕上打印杨辉三角。
1
1 1
1 2 1
1 3 3 1
……........

public class Main {
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        int[][] arr = new int[10][10];
        int i = 0;
        int j = 0;
        for (i = 0; i < 10; i++) {
            for (j = 0; j <= i; j++) {
                if (i == j) {
                    arr[i][j] = 1;
                }
                if (j == 0) {
                    arr[i][j] = 1;
                }
                if (i >= 2 && j >= 1) {
                    arr[i][j] = arr[i - 1][j] + arr[i - 1][j - 1];
                }
            }
        }
        for (i = 0; i < 10; i++) {
            for (j = 0; j <= i; j++) {
                System.out.print(arr[i][j] + " ");
            }
            System.out.println();
        }
    }
}

 【刷题宝典NO.3】_第1张图片

消失的数字

https://leetcode.cn/problems/missing-number-lcci/description/?envType=list&envId=OoMH8xH5

数组nums包含从0n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?

注意:本题相对书上原题稍作改动

示例 1:

输入:[3,0,1]
输出:2

示例 2:

输入:[9,6,4,2,3,5,7,0,1]
输出:8
class Solution {
    /*
    解题思路:
    直接将数组中所有元素之和sum,然后求出1~N的前N项和-sum即可
    时间复杂度O(N),空间复杂度:O(1)
    缺陷:如果数组中元素比较多,相加完成之后容易溢出
     */
    public int missingNumber1(int[] nums) {
        int sum = 0;
        for(int i = 0; i < nums.length; ++i){
            sum += nums[i];
        }
 
 
        return ((1+nums.length)*nums.length)/2 - sum;
    }
 
    /*
        解题思路:
          采用异或的方式解决,因为两个相同的数字异或的结果是0
          因此:将0~N之间的数字,与数组中的每个数字异或,
                最终的结果就是丢失的数字
     */
    public int missingNumber2(int[] nums) {
        int data = 0;
        for(int i = 0; i < nums.length; ++i){
            data ^= nums[i];
            data ^= i;
        }
        data ^= nums.length;
        return data;
    }
 
    /*
        解题思路:
        将1~N之间的数组相加,然后减去nums数组中的每个数字
     */
    public int missingNumber(int[] nums) {
        int data = nums.length;
        for(int i = 0; i < nums.length; ++i){
            data = data - nums[i] + i;
        }
        return data;
    }
}

删除有序数组中的重复项(I)

https://leetcode.cn/problems/remove-duplicates-from-sorted-array/description/?envType=list&envId=OoMH8xH5

给你一个 升序排列 的数组 nums ,请你** 原地 (opens new window)** 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。

由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。

将最终结果插入 nums 的前 k 个位置后返回 k 。

不要使用额外的空间,你必须在 **原地  (opens new window)**修改输入数组并在使用 O(1) 额外空间的条件下完成。

判题标准:

系统会用下面的代码来测试你的题解:

int[] nums = [...]; // 输入数组
int[] expectedNums = [...]; // 长度正确的期望答案

int k = removeDuplicates(nums); // 调用

assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
    assert nums[i] == expectedNums[i];
}

如果所有断言都通过,那么您的题解将被 通过

示例 1:

输入:nums = [1,1,2] 输出:2, nums = [1,2,_] 解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。

示例 2:

输入:nums = [0,0,1,1,1,2,2,3,3,4] 输出:5, nums = [0,1,2,3,4] 解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。

提示:

  • 1 <= nums.length <= 3 * 10^4
  • -10^4 <= nums[i] <= 10^4
  • nums 已按 升序 排列
/**
    解题思路:双指针思想  一个指针对数组遍历,一个指针指向即将被赋值的位置
    1.遍历数组中的每个元素
    2.当前被遍历的元素跟上一个元素进行比较,如果当前元素跟上个元素不同,那么就保存,相同就跳过。
 */
 
class Solution {
    public int removeDuplicates(int[] nums) {
        //指针 j 指向即将被赋值的位置
        int j = 0;
        //指针 i 进行数组遍历
        for (int i = 0; i < nums.length; i++) {
            if (i == 0 || nums[i] != nums[i - 1]) {
                //i == 0说明是第一个元素,第一个元素要先赋值,因为它前面没有元素,每次遍历的时候要比较当前元素和它上一个元素的值,如果不相等,说明不重复,就需要赋值
                nums[j] = nums[i];
                //一旦赋值了说明此时的nums[j]上有元素了,有元素就要让j向下一个位置移动,因为j是指向即将被赋值的位置,相当于占个位置
                j++;
            }
        }
        //遍历完成之后,直接返回j即可,数组索引的特性,索引代表几就说明前面有几个元素
        return j;
    }
}

删除有序数组中的重复项(II)

移除元素

https://leetcode.cn/problems/remove-element/description/?envType=list&envId=OoMH8xH5

给你一个数组 nums 和一个值 val,你需要 原地 (opens new window)移除所有数值等于 val 的元素,并返回移除后数组的新长度。

不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 **原地  (opens new window)**修改输入数组。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

说明:

为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以**「引用」**方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
int len = removeElement(nums, val);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
    print(nums[i]);
}

示例 1:

**输入:**nums = [3,2,2,3], val = 3 **输出:**2, nums = [2,2] **解释:**函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。

示例 2:

输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3]
解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。

提示:

  • 0 <= nums.length <= 100
  • 0 <= nums[i] <= 50
  • 0 <= val <= 100
class Solution {
    // public int removeElement(int[] nums, int val) {
    //     /*
    //     1. 从前往后遍历nums,找到val第一次出现的位置
    //     2. 将val之后的所有元素整体往前搬移,即删除该val
    //     3. nums中有效元素个数减少一个
    //     循环进行上述操作,直到nums中所有值为val的元素全部删除完
    //     时间复杂度:O(N^2)  空间复杂度:O(1)
    //     */
    //     int size = nums.length;
    //     int i = 0;
    //     while(true){
    //         // 1. 在nums中找val的位置
    //         for(i = 0; i < size; ++i){
    //             if(nums[i] == val){
    //                 break;
    //             }
    //         }
 
    //         if(i == size){
    //             // nums中没有发现值为val的元素,直接跳出while
    //             break;
    //         }
 
    //         // 2. 将i位置之后所有元素整体往前搬移一个位置
    //         for(int pos = i+1; pos < size; ++pos){
    //             nums[pos-1] = nums[pos];
    //         }
 
    //         // 注意:一趟之后size一定要减去1,因为删除了一个val
    //         size--;
    //     }
    //     return size;
        
    // }
        /*
        解题思路: 
          1. 创建一个长度与nums相同的数组ret
          2. 遍历nums,将nums中所有与val不同的元素搬移到ret中
          3. 将ret中所有元素拷贝回nums中
          时间复杂度: O(N)  空间复杂度: O(N)
    */
    // public int removeElement(int[] nums, int val) {
    //     int[] ret = new int[nums.length];
    //     int size = 0;
    //     for(int i = 0; i < nums.length; ++i){
    //         if(nums[i] != val){
    //             ret[size++] = nums[i];
    //         }
    //     }
 
    //     System.arraycopy(ret, 0, nums, 0, size);
    //     return size;
    // }
    
 
     /*
        解题思路:
          1. 设置一个变量count,用来记录nums中值等于val的元素的个数
          2. 遍历nums数组,对于每个元素进行如下操作:
               a. 如果num[i]等于val,说明值为val的元素出现了一次,count++
               b. 如果nums[i]不等于元素,将nums[i]往前搬移count个位置
                  因为nums[i]元素之前出现过count个值等于val的元素,已经被删除了
                  因此此处需要将nums[i]往前搬移
          3. 返回删除之后新数组中有效元素个数
        
        时间复杂度:O(N)   空间复杂度:O(1)
     */
    //  public int removeElement(int[] nums, int val) {
    //     int count = 0;
    //     for(int i = 0; i < nums.length; ++i){
    //         if(nums[i] == val){
    //             count++;
    //         }else{
    //             nums[i - count] = nums[i];
    //         }
    //     }
 
    //     return nums.length - count;
    // }
    /**
    解题思路:双指针思想
    1.遍历数组中的每个元素
    2.遍历的元素跟val作比较,如果不等于val就保留,等于val就跳过
     */
    public int removeElement(int[] nums, int val) {
        //指针 j 指向即将被赋值的位置
        int j = 0;
        //指针 i 遍历数组
        for (int i = 0; i < nums.length; i++) {
            //进行筛选,如果每次遍历到的元素的值跟val不一样,就有资格留下来进行赋值
            if (nums[i] != val) {
                nums[j] = nums[i];
                //一旦赋值了说明此时的nums[j]上有元素了,有元素就要让j向下一个位置移动,因为j是指向即将被赋值的位置,相当于占个位置
                j++;
            }
        }
        //遍历完成之后,直接返回j即可,数组索引的特性,索引代表几就说明前面有几个元素
        return j;
    }
}

移动零

https://leetcode.cn/problems/move-zeroes/description/

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例 1:

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

示例 2:

输入: nums = [0]
输出: [0]

提示:

  • 1 <= nums.length <= 10^4
  • -2^31 <= nums[i] <= 2^31 - 1
class Solution {
    /**
    解题思路:双指针
    1.指针 i 遍历数组的每个元素
    2.遍历的元素如果非 0,就赋值且让指针 j 向后移动,为 0 就跳过
    3.因为有几个非 0 的元素,j就会向后移动几个位置,即 j 前面的都是非 0 元素,j指向所有为 0 元素的第一个位置,后面都是为 0 的元素
    时间复杂度:O(n),其中 n 为序列长度。每个位置至多被遍历两次。
    空间复杂度:O(1)。只需要常数的空间存放若干变量。
     */
    public void moveZeroes(int[] nums) {
        // 指针 j 指向经过一系列操作后数组中所有为 0 元素的第一个位置上
        // 一开始默认在索引为 0 的位置
        int j = 0;
        // 指针 i 从头到尾遍历数组
        // 遍历完毕之后,j 指向了一个为 0 的元素,或者如果数组中不存在 0 ,就和 i 一样,超过了数组的范围
        for (int i = 0; i < nums.length; i++) {
            // 在遍历过程中,如果发现访问的元素是非 0 元素
            // 说明 j 不在正确的位置上,需要向后移动,寻找合适的位置
            if (nums[i] != 0) {
                // 这个时候,原先 j 的值需要被 i 的值覆盖
                nums[j] = nums[i];
                // j 需要向后移动,寻找合适的位置
                j++;
            }
        }
        // 接下来,只需要把 j 及其后面所有的元素都设置为 0 就行,因为 j 指向是所有为 0 元素的第一个位置上
        for (int i = j; i < nums.length; i++) {
            // 都设置为 0 
            nums[i] = 0;
        }
    }
}

最大连续 1 的个数

给定一个二进制数组 nums , 计算其中最大连续 1 的个数。

示例 1:

输入:nums = [1,1,0,1,1,1] 输出:3 解释:开头的两位和最后的三位都是连续 1 ,所以最大连续 1 的个数是 3.

示例 2:

输入:nums = [1,0,1,1,0,1] 输出:2

提示:

  • 1 <= nums.length <= 10^5
  • nums[i] 不是 0 就是 1.
public class Solution {
    public int findMaxConsecutiveOnes(int[] nums) {
        // 最后一个 0 所在的索引位置
        int lastZero = -1;
        // 结果
        int ans = 0;
        // 从左到右访问数组 nums
        for (int i = 0; i < nums.length; i++) {
            // 1、当前元素为 0 ,更新 lastZero 
            if (nums[i] == 0) {
                lastZero = i;
            }
            // 2、否则说明当前元素为 1
            else {
                // 通过 lastZero 可以获取当前元素距离最前面的 1 的个数
                // 对比之前的 ans ,更新获取最大值
                ans = Math.max(ans, i - lastZero);
            }
        }

        // 返回结果
        return ans;
    }
}

【刷题宝典NO.3】_第2张图片

改变原有数组元素的值

题目内容:
实现一个方法 transform, 以数组为参数, 循环将数组中的每个元素 乘以 2 , 并设置到对应的数组元素上. 例如 原数组为 {1, 2, 3}, 修改之后为 {2, 4, 6}

将数组里面的值 扩大2倍,有两种方式,一种是在自己本身上进行扩大,一种是新的数组中扩大。

/*import java.util.Arrays;
public class OnlineTest {
    public static int[] transFrom(int[] a) {
        for (int i = 0; i < a.length; i++) {
            a[i] *= 2;
        }
        return a;
    }
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        int[] array = {1, 2, 3};
        int[] ret = transFrom(array); //创建了一个变量和array同时指向array指向的那个数组,没创建新数组,但是多了个变量。
        System.out.println(Arrays.toString(ret));
    }
}*/
/*
import java.util.Arrays;
public class OnlineTest {
    public static void transFrom(int[] a) {
        for (int i = 0; i < a.length; i++) {
            a[i] *= 2;
        }
    }//无需返回值,直接在原数组上扩大二倍
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        int[] array = {1, 2, 3};
        transFrom(array);
        System.out.println(Arrays.toString(array));
    }
}*/
import java.util.Arrays;
public class OnlineTest {
    public static int[] transFrom(int[] a) {
        int[] tmpArray = new int[a.length];
        for (int i = 0; i < a.length; i++) {
            tmpArray[i] = a[i] * 2;
        }
        return tmpArray;
    }//返回新的数组的地址,两个不同的数组空间
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        int[] array = {1, 2, 3};
        int[] ret = transFrom(array);
        System.out.println(Arrays.toString(ret));
    }
}

【刷题宝典NO.3】_第3张图片

奇数位于偶数之前 

题目内容:
调整数组顺序使得奇数位于偶数之前。调整之后,不关心大小顺序。

如数组:[1,2,3,4,5,6]

调整后可能是:[1, 5, 3, 4, 2, 6]

 【刷题宝典NO.3】_第4张图片

import java.util.Arrays;
public class OnlineTest {
    public static void fun(int[] array) {
        //在数组的两端的下标分别同时向中间逼近,前提:left < right 左边:如果是奇数就让指针++,右边:如果是偶数就让指针--,
        int left = 0;
        int right = array.length - 1;
        while (left < right) {
            while (left < right && array[left] % 2 != 0) {//奇数 如果全是奇数,left一直++,left>right,下标不准确,交换会出现错误
                left++;
            }
            while (left < right && array[right] % 2 == 0) {//偶数 如果全是偶数,right一直--,right

 【刷题宝典NO.3】_第5张图片

二分查找 

题目内容:
给定一个有序整型数组, 实现二分查找

【刷题宝典NO.3】_第6张图片

import java.util.Arrays;
public class OnlineTest {
    public static int myBinarySearch(int[] arr, int key) {
        int left = 0;
        int right = arr.length - 1;
        while (left <= right) {
            int mid = (left + right) / 2;// 每次中间下标是要发生变化的,要放在循环
            if (arr[mid] > key) {//查找的值小于中间值, 说明值在左边, 右下标变化
                right = mid - 1;
            } else if (arr[mid] < key) {//查找的值大于中间值, 说明值在右边, 左下标变化
                left = mid + 1;
            } else {
                return mid; //找到了,返回下标
            }
        }
        return -1; // 找不到返回-1
    }
    /*
     * 局面
     * 外接给我的任务、参数,称为局面
     * 经过一定的处理,变成一个新局面,
     * */
    //递归写法:
    public static int binarySearch(int[] arr, int left, int right, int target) {
        int midIndex = left + ((right - left) >> 1);
        int midValue = arr[midIndex];
        //递归调用 出口:找到值,规则:往右走或者往左走
        if (target > midValue) {//往右走
            return binarySearch(arr, midIndex + 1, right, target);
        } else if (target < midValue) {//往左走
            return binarySearch(arr, left, midIndex - 1, target);
        } else {
            return midIndex;
        }
    }
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        int ret1 = myBinarySearch(arr, 5);
        int ret2 = myBinarySearch(arr, 6);
        //递归调用:
        int ret3 = binarySearch(arr, 0, 3, 2);//在指定的下标范围查找target
        System.out.println(ret1);//4
        System.out.println(ret2);//-1
        System.out.println(ret3);//1
        System.out.println("-----");
        Arrays.sort(arr);// 注意:使用二分查找的前提是有序数组!!!
        System.out.println(Arrays.binarySearch(arr, 5));//4
        System.out.println(Arrays.binarySearch(arr, 6)); //-6 如果查找的数 > 最后一个元素,返回的值是:-(arr.length+1)
    }
}

【刷题宝典NO.3】_第7张图片

冒泡排序 

题目内容:
给定一个整型数组, 实现冒泡排序(升序排序)

【刷题宝典NO.3】_第8张图片

进一步优化,当数据在排序过程当中有序了,会在某一趟排序后,发现数据没有交换。
所以,每一趟排序完,都去检查是否发生了交换,没有交换证明数据已近有序,不需要再进行剩余趟数的排序了。

import java.util.Arrays;
public class OnlineTest {
    //如果数很多,意味着要比较很多趟,假如在前几趟就已经有序了,后面很多趟都不需要继续比较了,再比较就是浪费
    //假如第一趟有序了,第二趟没有发生交换才能说明当前数组有序
    public static void bubbleSort(int[] array) {
        for (int i = 0; i < array.length - 1; i++) { //有n个数,要比较n-1趟
            boolean flag = false; //每一趟都要有flag,因为不知道具体在哪一趟会有序
            for (int j = 0; j < array.length - 1 - i; j++) { //每趟只需比较n - 1 - i个数,不需要n-1个数,因为每趟都会找出一个最大值往右边放,比较的个数就会少一个
                if (array[j] > array[j + 1]) {
                    int tmp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = tmp;
                    flag = true; //此趟发生了交换
                }
                if (flag == false) {//说明此趟没有进行交换,可判断当前数组有序,停止后面的比较
                    return;
                }
            }
        }
    }
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        int[] array = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
        bubbleSort(array);
        System.out.println(Arrays.toString(array));
    }
}

 【刷题宝典NO.3】_第9张图片

两数之和 

题目内容:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9

输出:[0,1]

解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

本题最重要的一句话:假设每种输入只会对应一个答案
也就意味着不会有多个答案,暴力求解就是挨个匹配查找即可
如果想提升效率,需要用到哈希表来解答

import java.util.Arrays;
public class OnlineTest {
    public static int[] findTarget(int[] nums, int target) {
        int[] ret = {-1, -1};
        //int[] ret = new int[2];
        for (int i = 0; i < nums.length; i++) {//遍历这个数组
            for (int j = i + 1; j < nums.length; j++) {//从第二个数开始遍历
                if (nums[i] + nums[j] == target) {
                    /*ret = new int[]{i, j};*/
                    ret[0] = i;
                    ret[1] = j;
                    return ret;
                }
            }
        }
        return ret;
    }
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        int[] nums = {2, 7, 11, 15};
        int[] ret = findTarget(nums, 18);
        System.out.println(Arrays.toString(ret));
    }
}

 【刷题宝典NO.3】_第10张图片

只出现一次的数字 

题目内容:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。 

示例 1:

输入: [2,2,1]
输出: 1
示例 2:

输入: [4,1,2,1,2]
输出: 4

本题主要考察运算符:异或
异或的特点是:
1、n ^ n = 0;即两个相同的数字异或是0
2、0 ^ n = n;即0和任何数字进行异或,结果就是那个任何数字。

public int singleNumber(int[] nums) {
    // 用异或运算的性质可以巧妙的解决这个问题,因为数组中只有一个数字出现一次
    // 则其他出现两次的数字用异或运算后都是0,最终整个数组异或运算的结果即为所求。
    int ret = 0;
    for (int i : nums) {
        ret ^= i;
    }
    return ret;
}
public class OnlineTest {
    //0 ^ x = x    x ^ x = 0  异或有交换律,所以最终会剩下只出现一次的数字
    public static int findNum(int[] array) {
        int ret = array[0];
        for (int i = 1; i < array.length; i++) {
            ret ^= array[i];
        }
        return ret;
    }
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        int[] array = {2, 2, 1};
        int ret = findNum(array);
        System.out.println(ret);
    }
}

【刷题宝典NO.3】_第11张图片

多数元素

题目内容:
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数

大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在多数元素

示例 1:

输入:[3,2,3]
输出:3
示例 2:

输入:[2,2,1,1,1,2,2]
输出:2

常规办法:数组中出现次数超过一半的数字,一定是排好序之后,中间位置的数字。

import java.util.Arrays;

public class OnlineTest {
    public static int findMoreNum1(int[] array) {
        //先进行排序,因为是找多数元素:在数组中出现次数>n/2的元素,所以数组中间的那个数一定是多数元素
        Arrays.sort(array);
        return array[array.length / 2];
    }

    public static int findMoreNum2(int[] array) {
        int count = 0;
        int tmp = array[0];
        for (int i = 0; i < array.length; i++) {
            if (array[i] == tmp) {
                count++;
            } else if (array[i] != tmp) {
                count--;
            } /*else if (count == 0) { //这儿必须是if,如果一直array[i] != tmp, count--之后等于-1,没有执行此语句了
                count++;
                tmp = array[i];
            }*/
            if (count == 0) {
                //2 2 3 3 2,当count == 0时,说明此时已经遍历到第2个3了,此时count++之后=1,tmp = 3  i = 3
                //最后一次遍历,i = 4,array[4] = 2 != tmp = 3,count--之后=0,走if(count == 0)这个分支,count又++之后=1
                //此时赋值给tmp = array[4] = 2,即出现次数最多的那个数
                //总结:哪个数让count == 0了,下次计数就从它开始。
                count++;
                tmp = array[i];
            }
        }
        return tmp;
    }

    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        int[] array = {2, 2, 3, 3, 2};
        int ret1 = findMoreNum1(array);
        int ret2 = findMoreNum2(array);
        System.out.println(ret1);
        System.out.println("---");
        System.out.println(ret2);
    }
}

【刷题宝典NO.3】_第12张图片

【刷题宝典NO.3】_第13张图片

存在连续三个奇数的数组 

题目内容:
给你一个整数数组  arr,请你判断数组中是否存在连续三个元素都是奇数的情况:如果存在,请返回  true ;否则,返回  false 。

示例 1:

输入:arr = [2,6,4,1]

输出:false

解释:不存在连续三个元素都是奇数的情况。

示例 2:

输入:arr = [1,2,34,3,4,5,7,23,12]

输出:true

解释:存在连续三个元素都是奇数的情况,即 [5,7,23] 。

数字是连续出现的,所以我们只需要定义一个计数器,如果连续出现的次数超过3,则返回true。

import java.util.Arrays;
public class OnlineTest {
    public static boolean fun(int[] array) {
        int count = 0;
        for (int i = 0; i < array.length; i++) {
            if (array[i] % 2 != 0) {
                count++;
                if (count == 3) {
                    return true;
                }
            } else {
                count = 0;
            }
        }
        return false;
    }
    //这是一个main方法,是程序的入口:
    public static void main(String[] args) {
        int[] array = {1,3,5,2,4,6};
        boolean ret = fun(array);
        System.out.println(ret);
    }
}

【刷题宝典NO.3】_第14张图片

合并两个有序数组 

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。

请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。

示例 1:

输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。

示例 2:

输入:nums1 = [1], m = 1, nums2 = [], n = 0
输出:[1]
解释:需要合并 [1] 和 [] 。
合并结果是 [1] 。

示例 3:

输入:nums1 = [0], m = 0, nums2 = [1], n = 1
输出:[1]
解释:需要合并的数组是 [] 和 [1] 。
合并结果是 [1] 。
注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。

提示:

  • nums1.length == m + n
  • nums2.length == n
  • 0 <= m, n <= 200
  • 1 <= m + n <= 200
  • -109 <= nums1[i], nums2[j] <= 109
class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int i = m - 1;
        int j = n - 1;
        int k = m + n - 1;
        //两个数组都有元素
        while (i >= 0 && j >= 0) {
            if (nums1[i] <= nums2[j]) {
                nums1[k] = nums2[j];
                j--;
                k--;
            } else {
                nums1[k] = nums1[i];
                i--;
                k--;
            }
        }
        //nums1走完了,nums2里面还有元素没拷贝到nums1
        while (j >= 0) {
            nums1[k] = nums2[j];
            j--;
            k--;
        }
    }
}

【刷题宝典NO.3】_第15张图片 【刷题宝典NO.3】_第16张图片

旋转数组 

https://leetcode.cn/problems/rotate-array/description/?envType=list&envId=OoMH8xH5

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

示例 1:

输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]

示例 2:

输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释: 
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]

提示:

  • 1 <= nums.length <= 105
  • -231 <= nums[i] <= 231 - 1
  • 0 <= k <= 105
/*
    解题思路:
    按照题目所说,进行k次旋转,每次旋转移动一个字符
    注意:k如果超过nums的长度时,对k取模
    时间复杂度: O(KN)
    思路没有问题,但是会时间复杂度会超
*/
/*
class Solution {
    public void rotate(int[] nums, int k) {
        k %= nums.length;
        for(int i = 0; i < k; ++i){
            // 将数组中前n-1个元素整体往后搬移一个位置
            int last = nums[nums.length-1];
            for(int j = nums.length-1; j >= 1; --j){
                nums[j] = nums[j-1];
            }
            // 将搬移前最后一个元素放到数组0号位置
            nums[0] = last;
        }
    }
}
*/
 
/*
  解题思路:使用三次逆转法,让数组旋转k次
    1. 整体逆置 
    2. 逆转子数组[0, k - 1]
    3. 逆转子数组[k, size - 1]
*/
class Solution {
    void rotate(int[] nums, int left, int right){
        while(left < right){
            int temp = nums[left];
            nums[left] = nums[right];
            nums[right] = temp;
            left++;
            right--;
        }
    }
    public void rotate(int[] nums, int k) {
        k %= nums.length;
        rotate(nums, 0, nums.length-1);
        rotate(nums, 0, k-1);
        rotate(nums, k, nums.length-1);
    }
}

【刷题宝典NO.3】_第17张图片

你可能感兴趣的:(算法训练(不定期更),算法,java,数据结构,1024程序员节)