算法一点点|青训营笔记

102 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

这是我参与「第四届青训营」笔记创作活动的的第5天 今天课程需要消化一下,就写两道算法趴~

T278 第一个错误的版本

题目描述:

你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。

假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。

你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。

思路:

尽可能减少调用接口的次数,对于数组来说,小白目前只知道线性查找和二分查找,这里使用二分查找的办法,因为正确版本之后的版本都是错误版本,相当于数组升序排序,对于每次查找,都检查中间值,如果正确,那么错误版本一定位于右侧;如果错误,那么错误版本一定位于此位置或此位置左侧,分析时间复杂度为O(logn)。

JAVA:
public class Solution extends VersionControl {
    public int firstBadVersion(int n) {
        int left = 1, right = n;
        while (left < right) { 
            int mid = left + (right - left) / 2; 
            if (isBadVersion(mid)) {
                right = mid; 
            } else {
                left = mid + 1; 
            }
        }
        return left;
    }
}

T977 有序数组的平方

题目描述:

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

思路:

初始思路是遍历数组再排序,再进行快速排序,最后输出数组。

JAVA:
class Solution {
    public int[ ] sortedSquares(int[ ] nums) {
        for(int i=0;i<nums.length;i++){
            nums[i]=nums[i]*nums[i];//遍历数组
        }
        Arrays.sort(nums);
        return nums;
    }
}

再看完官方题解之后,有了新思路,采用双指针,升序正数平方之后仍为升序,升序负数平方之后仍为降序,利用负数与正数的分界线,就可以得到两个有序的数组,使用归并排序进行排序,使用两个指针,分别对应两个数组,选择较少的放进答案中,进而得出答案。时间复杂度也为O(n)。

JAVA:
class Solution {
    public int[] sortedSquares(int[] nums) {
        int n=nums.length;
        int flag=-1;
        for(int k=0;k<n;k++){
            if(nums[k]<0){//找出正数负数的分界
                flag=k;
            }
            else{
                break;
            }
        }
        //求解
        int k=0;
        int[] ans = new int[n];//定义同样长度的数组
        int i=flag,j=flag+1;
        while(i>=0||j<n){
            if (i < 0) {
                ans[k] = nums[j] * nums[j];
                ++j;
            } else if (j == n) {
                ans[k] = nums[i] * nums[i];
                --i;
            } else if (nums[i] * nums[i] < nums[j] * nums[j]) {
                ans[k] = nums[i] * nums[i];
                --i;
            } else {
                ans[k] = nums[j] * nums[j];
                ++j;
            }
            ++k;
        }
        return ans;
    }
}

T189 轮转数组

题目描述:

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

思路:

初始思路是使用额外数组进行存储,但题目要求空间复杂度为O(1),emmm,可以考虑原地置换,明天再写···

class Solution {
    public void rotate(int[] nums, int k) {
        int n = nums.length;
        int[] newArr = new int[n];
        for (int i = 0; i < n; ++i) {
            newArr[(i + k) % n] = nums[i];
        }
        System.arraycopy(newArr, 0, nums, 0, n);
    }
}