第一次尝试leetcode刷题,突然发现算法题也没有想象中的那么困难

说明:从学习javase开始到如今,已经学习了接近四个月的时间了,虽然疫情让我出不了门。但是也正是疫情这个机会,让我看到了编程的“美”。体会到了编程的乐趣,五月份,跌跌撞撞简单的学完了数据结构与算法。接下来的一段时间,可能到下学期开学,都将学习框架,然后争取每天一到两道算法题。现在的学习状态感觉也到了瓶颈,处于下滑时期。加油吧,小伙子!早点调整好状态,继续前行。共勉。接下来的leetcode刷题这个小的系列,相当于我的错题本,自己能够解决的题目就不再一个一个放在上面了。

题一:给定一个未经排序的整数数组,找到最长且连续的的递增序列。

暴力解题:

  1. 对数组进行排序
  2. 遍历原数组,与排序后的数组比较,找出最长的连续序列即可

代码:

 public static int getMaxLenght(int[] arr) {
        if(arr.length == 0)return 0;
        int count = 0;//用来存储最长的序列长度
        int temp = 1;//记录当前数据的递增长度
        for (int i = 0; i < arr.length - 1; i++) {
            if (arr[i] < arr[i + 1]) {
                temp++;
            } else {
                if (count < temp) count = temp ;
                temp = 1;
            }
        }
        if (temp > count) return temp ;
        return count;
    }

题二:一个长度为n-1的递增排序数组中的所有数字都是唯一的, 并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中, 请找出这个数字。

思路:

  1. 暴力解题:从数组尾部遍历,直接找出。

  2. 二分法

代码:

  1. 暴力:
 public static int getMiss(int[] sums) {
        if (sums.length == 1) {
            if (sums[0] == 0) return 1;
            else return 0;
        }
        int sun = sums.length;//表示最大的数字
        int index = sums.length - 1;//索引
        while (index >= 0) {
            if (sun != sums[index]) return sun;
            else sun--;
            index--;
        }
        return -1;
    }
  1. 二分法:
 public static int getMiss2(int[] sums) {
        int i = 0, j = sums.length - 1;
        while (i <= j) {
            int m = (i + j) / 2;
            if (sums[m] == m) i = m + 1;
            else j = m - 1;
        }
        return i;
    }

题三: 学校在拍年度纪念照时,一般要求学生按照 非递减 的高度顺序排列。请你返回能让所有学生以 非递减 高度排列的最小必要移动人数。注意,当一组学生被选中时,他们之间可以以任何可能的方式重新排序,而未被选中的学生应该保持不动。

思路:

  1. 对表示学生身高的数组排序,得到一个排序后的新数组
  2. 对比排序后数组和原数组,记录下标值相同但元素值不同的下标个数,即为排错位置的学生个数

代码:

 public static int getSum(int[] arr) {
        int[] temp = Arrays.copyOf(arr, arr.length);
        //排序
        Arrays.sort(temp);
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == temp[i]) continue;
            else sum++;
        }
        return sum;
    }

思路二(最优思路)

  1. 首先我们其实并不关心排序后得到的结果,我们想知道的只是在该位置上,与最小的值是否一致 题目中已经明确了值的范围 1 <= heights[i] <= 100
  2. 这是一个在固定范围内的输入,比如输入: [1,1,4,2,1,3] 输入中有 3 个 1,1 个1 个 3 和 1 个 4,3 个 1 肯定会在前面,依次类推
  3. 所以,我们需要的仅仅只是计数而已
 public static int getSum2(int[] arr) {
        int[] temp = new int[101];
        for (int a : arr) {
            temp[a]++;
        }
        int count = 0;
        for (int i = 0, j = 0; i < temp.length; i++) {
            while (temp[i] > 0) {//说明原数组当中这索引所在的地方是有数字的
                //说明位置不正确
                if(arr[j++] != i)count++;
                temp[i]--;
            }
        }
        return count;
    }

题四:给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

思路:
方法:双指针法

 1. 数组完成排序后,我们可以放置两个指针 ii 和 jj,
 其中 ii 是慢指针,而 jj 是快指针。只要 nums[i] = nums[j]nums[i]=nums[j],
 我们就增加 jj 以跳过重复项。
 2. 当我们遇到 nums[j]不等于nums[i] nums[j]=nums[i] 时,
 跳过重复项的运行已经结束,因此我们必须把它(nums[j]nums[j])的值复制到 
 nums[i + 1]nums[i+1]。
 然后递增 ii,接着我们将再次重复相同的过程,直到 jj 到达数组的末尾为止。

代码:

public static int getNewLenght(int[] nums) {
        if (nums.length == 1 || nums.length == 0) return nums.length;
        int j = 0;
        for (int i = 1; i < nums.length; i++) {
            if(nums[i] == nums[j]){
               continue;
            }else {
                j++;
                nums[j] = nums[i];
            }
        }
        return j+1;
    }

题五:给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。

说明:

初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。
你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。

第一思路:直接合并,然后对数组排序

代码:

class Solution {
  public void merge(int[] nums1, int m, int[] nums2, int n) {
    System.arraycopy(nums2, 0, nums1, m, n);
    Arrays.sort(nums1);
  }
}

思路二:最直接的算法实现是将指针p1 置为 nums1的开头, p2为 nums2的开头,在每一步将最小值放入输出数组中。

在这里插入图片描述
代码:

class Solution {
  public void merge(int[] nums1, int m, int[] nums2, int n) {
    int [] nums1_copy = new int[m];
    System.arraycopy(nums1, 0, nums1_copy, 0, m);

    int p1 = 0;
    int p2 = 0;

    int p = 0;
    while ((p1 < m) && (p2 < n)) nums1[p++] = (nums1_copy[p1] < nums2[p2]) ?
    nums1_copy[p1++] : nums2[p2++];
    if (p1 < m)
      System.arraycopy(nums1_copy, p1, nums1, p1 + p2, m + n - p1 - p2);
    if (p2 < n)
      System.arraycopy(nums2, p2, nums1, p1 + p2, m + n - p1 - p2);
  }
}

猜你喜欢

转载自blog.csdn.net/qq_44895397/article/details/106395677