69.x的平方根
给你一个非负整数 x
,计算并返回 x
的 算术平方根 。
由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
本题的核心在于找到第一个平方数大于x的数
1. 二分法:找到第一个平方数大于x的数
注意点是:mid*mid需要转成(long long)
class Solution {
public:
int mySqrt(int x) {
int left = 0;
int right = x;
int ans;
while(left <= right) {
int mid = left + (right - left) / 2;
if((long long)mid * mid <= x) {
ans = mid;
left = mid + 1;
} else {
right = mid - 1;
}
}
return ans;
}
};
367.有效的完全平方数
给你一个正整数 num
。如果 num
是一个完全平方数,则返回 true
,否则返回 false
。
完全平方数 是一个可以写成某个整数的平方的整数。换句话说,它可以写成某个整数和自身的乘积。
注意点:mid*mid需要转成(long long)
1. 双指针:类似于 704.二分查找
class Solution {
public:
bool isPerfectSquare(int num) {
int left = 0;
int right = num;
while(left <= right) {
int mid = left + (right - left) / 2;
if((long long)mid * mid > num) {
right = mid - 1;
} else if((long long)mid * mid < num) {
left = mid + 1;
} else {
return true;
}
}
return false;
}
};
27.移除元素
给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1)
额外空间并 原地 修改输入数组。
1. 暴力解法:暴力解法首先一层for循环遍历数组,找到与val相等的数,然后用该数的下一个数把这个数覆盖掉。关键点在于:覆盖不能只覆盖一个数,必须把后面完整的所有的剩余数组全部左移
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int size = nums.size();
for(int i = 0; i < size; i++) {
if(val == nums[i]) {
for(int j = i + 1; j < size; j++) {
nums[j - 1] = nums[j];
}
i--;
size--;
}
}
return size;
}
};
2. 双指针:快慢指针,快指针遍历整个数组,找到与val值不相等的数,将其存入慢指针指向的数组
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowIndex = 0;
for(int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
if(val != nums[fastIndex]) {
nums[slowIndex++] = nums[fastIndex];
}
}
return slowIndex;
}
};
26. 删除数组中的重复项
给你一个 非严格递增排列 的数组 nums
,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums
中唯一元素的个数。
考虑 nums
的唯一元素的数量为 k
,你需要做以下事情确保你的题解可以被通过:
- 更改数组
nums
,使nums
的前k
个元素包含唯一元素,并按照它们最初在nums
中出现的顺序排列。nums
的其余元素与nums
的大小不重要。 - 返回
k
。
1. 暴力解法:首先一层for循环遍历数组,找到前后相等的两个数,然后用相等数后一个的下一个数把该数覆盖掉,要用后面整个完整数组覆盖该点的数组
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int size = nums.size();
for(int i = 0; i < size - 1; i++) {
if(nums[i] == nums[i + 1]) {
for(int j = i + 2; j < size; j++) {
nums[j - 1] = nums[j];
}
i--;
size--;
}
}
return size;
}
};
2. 双指针:细节点在于不需要完整遍历整个数组,因为最后一个数,在比较前后项的时候已经比较过了,而且赋值的时候也是赋值相等项的后一个
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if (nums.empty()) return 0; // 别忘记空数组的判断
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < (nums.size() - 1); fastIndex++){
if(nums[fastIndex] != nums[fastIndex + 1]) { // 发现和后一个不相同
nums[++slowIndex] = nums[fastIndex + 1]; //slowIndex = 0 的数据一定是不重复的,所以直接 ++slowIndex
}
}
return slowIndex + 1; //别忘了slowIndex是从0开始的,所以返回slowIndex + 1
}
};
3. 将vector转化为set 哈希表可以进行去重操作,再从set转到vector(我只能说,看了题解这个老哥,确实牛逼,真有想法吧)
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
set<int> s;
int len = nums.size();
for(int i = 0; i < len; i++) {
s.insert(nums[i]);
}
len = s.size();
nums.clear();
for(const int & element : s) {
nums.push_back(element);
}
return len;
}
};
283.移动零
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
1.暴力解法:遇到0就交换0和不为0的数
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int j = 0;
for(int i = 0; i < nums.size(); i++) {
if(nums[i]) swap(nums[i], nums[j++]);
}
}
};
2. 双指针:将不为0的数存入慢指针数组,传入完毕后,将数组最后补0
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int slow = 0;
for(int fast = 0; fast < nums.size(); fast++) {
if(0 != nums[fast]) {
nums[slow++] = nums[fast];
}
}
for(int i = slow; i < nums.size(); i++) {
nums[i] = 0;
}
}
};
977.有序数组的平方
给你一个按 非递减顺序 排序的整数数组 nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
1. 暴力+排序:先将所有元素的平方存入新数组,在进行sort快排
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
vector<int> vec(nums.size());
for(int i = 0; i < nums.size(); i++) {
vec[i] = nums[i] * nums[i];
}
sort(vec.begin(), vec.end());
return vec;
}
};
2. 双指针:比较头指针的平方和尾指针的平方,将大的那一个存入新数组的尾部,从新数组的尾部一直慢慢添加到新数组的头部
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int left = 0;
int right = nums.size() - 1;
vector<int> vec(nums.size());
int i = nums.size() - 1;
while(left <= right) {
if(nums[left] * nums[left] > nums[right] * nums[right]) {
vec[i--] = nums[left] * nums[left];
left++;
} else {
vec[i--] = nums[right] * nums[right];
right--;
}
}
return vec;
}
};
感谢代码随想录,感谢Carl神