简单学过C++语法,自己也刷过一些算法题(20来道),但感觉不成系统。这次就从头系统的学一学!
704二分查找
知识点:二分查找 状态:一遍过(可能是因为之前做过有肌肉记忆)
思路: 如果只有一个数,直接比较; 多个数时先用l,r,定义左右边界,每次比较mid=(l+r)/2的数字,如果target>num[mid],移动左边界l到mid+1,用while(l<=r)循环(因为l可以等于r)。
代码:
class Solution {
public:
int search(vector<int>& nums, int target)
{
int n = nums.size();
if ( n == 1)
{
if ( nums[0] == target )
{
return 0;
}
return -1;
}
else
{
int left = 0 , right = n-1 ;
while ( left <= right )
{
int mid = ( left + right ) / 2 ;
if( nums[mid] == target)
{
return mid;
}
else if ( target < nums[mid] )
{
right = mid-1;
}
else
{
left = mid+1;
}
}
return -1;
}
}
};
结果:
27 移除元素
知识点:删除、数组 状态:暴力有小瑕疵;快慢指针看了思路才写出来
方法一 思路: 暴力法,遍历两遍,但此时只对了85/113个。
输入:[0,1,2,2,3,0,4,2] 2 实际输出: [0,1,2,3,0,4] 正确结果: [0,1,3,0,4]
原因是因为在删除位置2的2后,此时第一个for循环i为2,并将位置3的2移到了位置2,循环结束,i从位置3开始,将第二个数字2跳了过去,导致错误结果。
解决: 因为后边所有数字都往前移了一个位置,所以i也往前移动一个即可
暴力代码:
class Solution {
public:
int removeElement(vector<int>& nums, int val)
{
int size = nums.size();
for (int i = 0 ; i <= size-1 ; i++ )
{
if ( nums[i] == val )
{
for ( int j = i ; j <= size-2 ; j++)
{
nums[j]=nums[j+1];
}
--i; // 改正后添加的一行,将i也往前移动一个
--size;
}
}
return size;
}
};
方法二 思路:快慢指针
right (快指针)为正在遍历的原数组的元素位置,left (慢指针)是指当right 不为 val 的话,将要把right的值插入新数组的位置。(新数组就是在原数组上直接改,while循环结束后,left就是长度)
left就是长度的原因: left指向的是将要插入的位置,是实际插入后的位置+1;而数组长度是最后一个元素位置+1(因为还有一个0位置的元素)。
当循环结束时,left指向的就是最后一个元素位置+1,即数组长度。
代码:
//快慢指针
class Solution {
public:
int removeElement(vector<int>& nums, int val)
{
int n = nums.size();
if ( n == 0 )
{return 0;}
int left = 0 , right = 0 ; // right (快指针)为遍历数组的元素位置,left (慢指针)是如果right 不为 val 的话,将要插入数组的位置。
while ( right < n ) // right 遍历到最后跳出循环
{
if ( nums[right] == val )
{
++right;
}
else
{
nums[left] = nums[right] ;
++left;
++right;
}
}
return left;
}
};