数组nums包含从0到n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?
注意:本题相对书上原题稍作改动
示例 1:
输入:[3,0,1]
输出:2
示例 2:
输入:[9,6,4,2,3,5,7,0,1]
输出:8
思路:
由于缺失一个数,所以可以先计算出 0~n 的异或结果,再依次与数组中的元素异或,最后的结果就是缺失的数字
int missingNumber(int* nums, int numsSize){
int x=0;
for(int i=0;i<=numsSize;i++)
{
x^=i;// 计算 0~n 的异或结果
}
for(int i=0;i<numsSize;i++)
{
x^=nums[i];// 依次异或数组中的元素
}
return x;
}
给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。
示例 1:
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]
示例 2:
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释:
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]
思路1:
每次将数组最后一个元素取出并放到数组的开头,重复 k 次操作实现数组的旋转
思路2:
利用双指针,将范围内的元素进行交换
对 k 进行取模处理,避免 k 大于数组长度造成多余的旋转
// 时间复杂度 O(N*K)
void rotate(int* nums, int numsSize, int k) {
while(k--)
{
int temp=nums[numsSize-1];
for(int end=numsSize-2;end>=0;end--)
nums[end+1]=nums[end];
nums[0]=temp;
}
}
// 时间复杂度 O(1)
void Reverse(int nums,int left,int right)
{
while(left < right)
{
int temp=nums[left];
nums[left]=nums[right];
nums[right]=temp; left++; right--;
}
}
void rotate(int nums, int numsSize, int k) {
if(k >= numsSize)
{
k=k%numsSize; // 对 k 进行取模处理,避免 k 大于数组长度造成多余的旋转
}
// 1 2 3 4 7 6 5
Reverse(nums,numsSize-k,numsSize-1); // 反转后面的 k 个元素
// 4 3 2 1 7 6 5
Reverse(nums,0,numsSize-k-1); // 反转前面的 numsSize - k 个元素
// 5 6 7 1 2 3 4
Reverse(nums,0,numsSize-1); // 反转整个数组
}
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
思路:
使用双指针,一个指向源位置,一个指向目标位置,遍历数组,并将不等于目标值的元素移到前面
int removeElement(int* nums, int numsSize, int val) {
int src=0; // 源位置指针
int dst=0; // 目标位置指针
while(src < numsSize)
{
if(nums[src]!=val) // 当源位置指针指向的元素不等于目标值时
{
nums[dst]=nums[src]; // 将该元素移到目标位置
dst++; // 目标位置指针后移
src++; // 源位置指针后移
}
else
src++; // 当源位置指针指向的元素等于目标值时,只移动源位置指针
}
return dst; // 返回移除目标值后的新数组长度
}
给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
示例 1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6]
思路:
思路:从后向前合并两个数组,将较大的数字放到 nums1 的末尾,直到所有元素都被合并
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
// 将较大的数字放到nums1中
int end1=m-1; // 第一个数组的末尾指针
int end2=n-1; // 第二个数组的末尾指针
int end=m+n-1; // 合并后数组的末尾指针
while(end1>=0 && end2>=0) // 循环直到其中一个数组的元素全部合并完成
{
if(nums1[end1] > nums2[end2]) // 比较两个数组末尾的元素大小
{
nums1[end]=nums1[end1]; // 将较大的元素放到合并后数组的末尾
end--; // 指针前移
end1--; // 数组1的末尾指针前移
}
else
{
nums1[end]=nums2[end2]; // 将较大的元素放到合并后数组的末尾
end--; // 指针前移
end2--; // 数组2的末尾指针前移
}
}
while(end2 >= 0) // 若数组2还有剩余元素
{
nums1[end]=nums2[end2]; // 将剩余的元素放到合并后数组的末尾
end--; // 指针前移
end2--; // 数组2的末尾指针前移
}
}