携手创作,共同成长!这是我参与「掘金日新计划 · 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);
}
}