27.移除元素
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
int removeElement(int* nums, int numsSize, int val)
{
//开空间的做法
int *newArr=(int*)malloc(sizeof(int)*numsSize);
int idx=0;//数组起始存放位置
for(int i=0;i<numsSize;++i)
{
if(nums[i]!=val)
{
newArr[idx++]=nums[i];
}
}
memcpy(nums,newArr,sizeof(int)*idx);//拷贝idx个有效的数据
free(newArr);
return idx;
//不开空间的做法
int idx=0;
for(int i=0;i<numsSize;++i)
{
if(nums[i]!=val)
{
nums[idx++]=nums[i];
}
}
return idx;
}
26.删除有序数组中的重复项
给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
思路:i是每个要保存的位置,把它保存在idx上(idx每次只加1),通过判断 i和j 来找到下一个不同的位置
最后一个元素 下标是numsSize-1;
int removeDuplicates(int* nums, int numsSize)
{
if(numsSize<=1)
return numsSize;
int i=0,j=1,idx=0;
while(j<numsSize)//j越界
{
nums[idx++]=nums[i];
//判断元素是否重复
if(nums[i]==nums[j])
{
//找到重复元素的结束位置
while(j<numsSize&&nums[i]==nums[j])
++j;//while退出时,j的位置是下一个不相同的
i=j;//下一个保存的位置
++j;
}
else
{
++i;
++j;
}
}
//最后一个位置时,j会越界,此时i走到最后一个位置
if(i<numsSize)
{
//保存最后一个数据
nums[idx++]=nums[i];
}
return idx;
}
88. 合并两个有序数组
给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{
//不开空间的做法
int i=m-1;
int j=n-1;
int max=m+n-1;
while(i>=0&&j>=0)
{
if(nums2[j]>nums1[i])
{
nums1[max--]=nums2[j--];
}
else
{
nums1[max--]=nums1[i--];
}
}
if(j>=0)
{
for(;j>=0;j--)
nums1[j]=nums2[j];//剩余的直接给赋值过去,nums2中有剩余元素
//memcpy(nums1,nums2,sizeof(int)*(j+1));
}
}
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{
//开空间的做法
int *nums3=(int*)malloc(sizeof(int)*(m+n));
int i=0,j=0,idx=0;
//同时遍历,从后向前插入
while(i<m&&j<n)
{
if(nums1[i]<nums2[j])
{
nums3[idx++]=nums1[i++];
}
else
{
nums3[idx++]=nums2[j++];
}
}
//直接拷贝剩余元素
if(i<m)
{
memcpy(nums3+idx,nums1+i,sizeof(int)*(m-i));
}
if(j<n)
{
memcpy(nums3+idx,nums2+j,sizeof(int)*(n-j));
}
memcpy(nums1,nums3,sizeof(int)*(m+n));
free(nums3);
}
189. 旋转数组
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
void swap(int *x,int *y)
{
int tmp=*x;
*x=*y;
*y=tmp;
}
void reserve(int* nums,int i,int j)
{
while(i<j)
{
swap(&nums[i],&nums[j]);
++i;
--j;
}
}
void rotate(int* nums, int numsSize, int k){
//分三步旋转
k=k%numsSize;
reserve(nums,0,numsSize-k-1);
reserve(nums,numsSize-k,numsSize-1);
reserve(nums,0,numsSize-1);
return nums;
}
位操作符:
&:全1则1
|:全0则0
^(异或):相同为0,不同为1
x^x=0;
x^0=x;
|| 短路或。 A||B,只有当A为假的时候才会对B进行判断。若A为真,则不继续对B进行判断
三次异或可以交换两个数:
a=a^b;
b=a^b;
a=a^b;
989. 数组形式的整数加法
对于非负整数 X 而言,X 的数组形式是每位数字按从左到右的顺序形成的数组。例如,如果 X = 1231,那么其数组形式为 [1,2,3,1]。
给定非负整数 X 的数组形式 A,返回整数 X+K 的数组形式。
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
//可以先把数组倒转过来
void reverse(int *nums,int begin,int end)
{
//可以先把数组倒转过来
while(begin<end)
{
int tmp=nums[begin];
nums[begin]=nums[end];
nums[end]=tmp;
begin++;
end--;
}
}
int* addToArrayForm(int* A, int ASize, int K, int* returnSize){
//在一个新开的数组上,最后逆转结果就是了
int *ans=(int*)malloc(sizeof(int)*10001);//开的是10001个字节大小的空间
int i=ASize-1;
int reti=0;
int flag=0;//标志位
while(i>=0||K>0)
{
int x1=0;
if(i>=0)
{
x1=A[i];
i--;
}
int x2=0;
if(K>0)
{
x2=K%10;
K=K/10;
}
int ret=x1+x2+flag;
if(ret>9)
{
flag=1;
ret=ret%10;
}
else
{
flag=0;
}
ans[reti++]=ret;
}
//最后一个有进位
if(flag==1)
{
ans[reti++]=1;
}
//逆转
reverse(ans,0,reti-1);
*returnSize=reti;
return ans;
}
更好的申请内存的方法