写在开头,三月份开始陆续刷了代码随想录到动态规划,三天打鱼两天晒网,有时状态好一天快10道,懒惰时一个礼拜刷不了一个,不得行,做笔试题做的想鼠,我只是可怜的鼠鼠,下定决心,要每天跟着进度走,我这勉强算二刷,也是看到题大概有个思路,冲!
ps:我是自己做了一个文档,记得比较详细(题目和解析),这就当一个打卡的地方,只放思路和解析代码,今天整了老半天怎么在idea里刷题,推送到仓库里,还不是很熟练,明天试试看。
704:二分查找
思路:二分法是没问题的,也能想出来用while循环,但每次while循环里的条件都会写反,每一次,之前是反转链表输出,循环条件直接写了空根本没进去,习惯用左闭右开,但是边界还是有问题,返回去看一遍解析就能写对。
题目注意:给的是升序数组(有顺序),数组里元素不重复。
代码如下(左闭右开):
public int search(int[] nums, int target) {
int left=0;
int right=nums.length;
int mid=nums.length/2;
while(left<right){
mid=(right+left)/2;
if(nums[mid]<target){
left=mid+1;
}else if(nums[mid]>target){
right=mid;
}else{
return mid;
}
}
return -1;
}
左闭右闭:
public int search(int[] nums, int target) {
int left=0;
int right=nums.length-1;
int mid=(nums.length-1)/2;
while(left<=right){
mid=(left+right)/2;
if(nums[mid]>target){
right=mid-1;
}else if(nums[mid]<target){
left=mid+1;
}else{
return mid;
}
}
return -1;
}
要注意最开始右边开的话初始值为数组长度-1.
35 搜索插入位置
二分法:能找到的话就返回mid值,要是没找到的话返回right值,因为要是没找到,插入的位置肯定是最右边的下一个。
public int searchInsert(int[] nums, int target) {
int left=0;
int length=nums.length;
int right=length;
int mid=(left+right)/2;
while(left<right){
mid=(left+right)/2;
if(nums[mid]>target){
right=mid;
}
else if(nums[mid]<target){
left=mid+1;
}else{
return mid;
}
}
return right;
}
34 在排序数组中查找第一个和最后一个元素的位置
思路:左闭右闭会比较好做一些。一个找到左边的端点,另一个找右边。精髓在于相等时一个不断左移,一个不断右移。
public int[] searchRange(int[] nums, int target) {
int left=0;
int length=nums.length;
int right=length-1;
int first=-1;
int last=-1;
while(left<=right){
int mid=(left+right)/2;
if(nums[mid]==target){
first=mid;
right=mid-1;//zhongdian
}else if(nums[mid]>target){
right=mid-1;
}else{
left=mid+1;
}
}
left=0;
right=length-1;
while(left<=right){
int mid=(left+right)/2;
if(nums[mid]==target){
last=mid;
left=mid+1;//zhongdian
}else if(nums[mid]>target){
right=mid-1;
}else{
left=mid+1;
}
}
return new int[]{first,last};
}
27. 移除元素
双指针忘记怎么实现了,暴力法是想新建一个数组,循环遍历原先的数组,遇到指定值就计数+1,不是指定值挪到新数组,这样问题是新数组会有空值出现,测评时也不符合要求,得再遍历一遍新数组,增强for写错了。。no,错了,数组初始化时会全为0,这样怎么判断是初始化的0还是之前数组里的0。
根据解题方法里写的暴力法提示我提交出错,原因不明。
public int removeElement(int[] nums, int val) {
int size=nums.length;
for(int i=0;i<nums.length;i++){
if(nums[i]==val){
for(int j=i+1;j<size;j++){
nums[j-1]=nums[j];
}
i--;
size--;
}
}
return size;
}
双指针法:通过快慢两个指针在一个for循环下完成两个for循环的任务
快指针:在旧数组寻找新数组的元素。
慢指针:更新新数组的下标。
public int removeElement(int[] nums, int val) {
int slow=0;
for(int fast=0;fast<nums.length;fast++){
if(nums[fast]!=val){
nums[slow]=nums[fast];
slow++;
}
}
return slow;
}
解析里的动图对做题理解真的很有帮助,外层的快指针是一定会把整个旧数组都遍历到的,里面则是有了可以放进新数组的元素,放进去慢指针++。