804. 唯一摩尔斯密码词
这次没有任何技巧而言,感觉就是再次熟悉一下,二级指针空间的分配回收,库函数strcat()的使用
int uniqueMorseRepresentations(char ** words, int wordsSize){
char mossCode[26][5] = {
".-","-...","-.-.","-..",".","..-.","--.","....","..",".---",
"-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-",
"..-","...-",".--","-..-","-.--","--.."
};
char **result=(char **)malloc(sizeof(char *)*wordsSize);
for (int i = 0; i < wordsSize; i++) {
result[i]=(char *)malloc(sizeof(char)*49);//字符串最长为4,4*12+1
memset(result[i], 0, sizeof(char)*49);
}
int i,length,j,sum=0;
for(i=0;i<wordsSize;i++){
length=strlen(*(words+i));//行指针
for(j=0;j<length;j++){
strcat(result[i],mossCode[words[i][j]-'a']);//计算出words[i]的mosscode
}
}
for(i=0;i<wordsSize;i++){
for(j=i+1;j<wordsSize;j++){
if(strcmp(result[i],result[j])==0)
break;
}
if(j==wordsSize)
sum++;
}
for(i=0;i<wordsSize;i++)
free(result[i]);
free(result);
return sum;
}
1351. 统计有序矩阵中的负数
注意利用好,每行每列都是非递增排序就OK拉
int countNegatives(int** grid, int gridSize, int* gridColSize){
int i,j,m=gridSize,n=*gridColSize,sum=0,tap;
for(i=0;i<m;i++){
for(j=n-1;j>=0;j--){
if(grid[i][j]>=0){
tap=0;
break;
}
tap=-1;
}
if(tap==-1){
sum+=n;
}else{
sum+=n-j-1;
}
}
return sum;
}
1337. 方阵中战斗力最弱的 K 行
总的来说来说,是一个排序题,外加索引绑定(索引绑定可以用二维数组,也可结构体,至于其他方法,还没去了解)。
定义结构体大小不能用变量,阿偶
结构体学的很潜,我都不知道qsort能和结构体组合使用。returnSize是返回给主函数,来控住数组的打印的。
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
struct Node{
int index;
int power;
};
int cmp(const void *a,const void *b){
return (*(struct Node *)a).power - (*(struct Node *)b).power;//a-b从小到大排序b-a则为从大到小排序
}
int* kWeakestRows(int** mat, int matSize, int* matColSize, int k, int* returnSize){
int i,j,m=matSize,n=*matColSize;
struct Node nodes[101]={0};
for(i=0;i<m;i++){
nodes[i].index=i;
for(j=0;j<n;j++){
if(mat[i][j]==1){
nodes[i].power++;
}
}
}
qsort(nodes,m,sizeof(struct Node),cmp);
int *res = (int *)malloc(k * sizeof(int));
memset(res, 0, k * sizeof(int));
(*returnSize) = k;//估计主函数中调用了此形参
for(i=0;i<k;i++){
res[i]=nodes[i].index;
}
return res;
}
717. 1比特与2比特字符
这道题的思路还是满简单的。遍历到的数若为1,则i增2(因为只要遇到1。10,11都是存在的情况),反之则增1。对于0可以是单独的0,或者10,也即只有在最后两位为00的情况下,给定的字符串才是以0结束的。所以我们对0以及他的前一位进行校验即可。情况一共有两种(以下情况,i均指向数组bitsSize的倒数第二个数):
- 最后两位为00,因为bits[bitsSize-1]==0,所以循环结束的时候,字符串刚好以0结束
- 最后两位为10,最后循环结束i==bitsSize,越界拉
bool isOneBitCharacter(int* bits, int bitsSize){
int i;
bool flag=false;
for(i=0;i<bitsSize-1;){//前四次按照普通的循环写的结束条件为bitsSize,然后一直错一直错,搞的我怀疑人生,以为for中三个表达式的执行顺序记错了
if(bits[i]==1)
i+=2;
else
++i;
}
if(i==bitsSize-1)
flag=true;
return flag;
}
136. 只出现一次的数字
这道题的方法涉及到我的知识盲区,位运算的实际运用。但是在理论上我又是懂位运算的。下面我先讲讲我遇到这题时候的一些想法。
1.用额外的空间,且额外空间还未知,因为我不知道最大的数是几
[]中的数为给定的一组数,蓝色的数组为新开辟的数组。eg:第一位数字为4,则new[4]++;
- 先将nums排序,但我想到最快的方法就是快排,也要nlogn。
- 第三个当然就是大神的方法咯,位运算!!!
C语言位运算符:与(&)、或(|)、异或(^)、取反(!)、左移(<<)与右移(>>)。这些运算符只能用于整型操作数,即只能用于带符号或无符号的char,short,int与long类型。
异或运算具有交换律,也即进行运算时的顺序不会改变结果。[4,1,2,1,2],4——100(2),1——001(2),2——010(2),100001010001010=100
int singleNumber(int* nums, int numsSize){
int temp=nums[0],i;
if(numsSize>1){
for(i=1;i<numsSize;i++){
temp^=nums[i];
}
}
return temp;
}
1207. 独一无二的出现次数
- 因为arr[i]的范围是给定了的,所以可以用此方法。
- count1[]中最多只有arrSize个不为0的数,所以只用给count2[]申请arrSize个空间
- count1[]用于记录各个数出现的次数;count2[]用于记录次数的个数
- 既然我浪费了空间,不想在排序浪费时间了,所以用了count2[]
bool uniqueOccurrences(int* arr, int arrSize){
int i,j;
bool temp=true;
int *count1=(int *)malloc(sizeof(int)*2001);
memset(count1,0,sizeof(int)*2001);
int *count2=(int *)malloc(sizeof(int)*(arrSize+1));
memset(count2,0,sizeof(int)*(arrSize+1));
for(i=0;i<arrSize;i++){
if(arr[i]>=0)
count1[arr[i]]++;
else
count1[arr[i]+2000]++;
}
for(j=0;j<2001;j++){
if(count1[j]>0)
count2[count1[j]]++;
if(count2[count1[j]]>1)
temp=false;
}
free(count1);
free(count2);
return temp;
}
54. 螺旋矩阵
注意墙壁的更新,这道题我自己在DEVc++ 5.11里调试过,然后喃,将二维数组直接传给二级指针是会报错的,原因是因为二维数组的二维是个假概念,在实际存储中都是一维存储,所以会报错。那么改为传指针数组就好拉……
int* spiralOrder(int** matrix, int matrixSize, int* matrixColSize, int* returnSize){
if(matrixSize==0){//注意考虑为空的情况
*returnSize=0;
return 0;
}
int left=0,right=*matrixColSize-1,up=0,down=matrixSize-1,length=matrixSize*(*matrixColSize);
int i,j,k=0;//i,j交替动
int *res=(int *)malloc(sizeof(int)*length);
while(left<=right&&up<=down&&k<length){//往右
i=up,j=left;
while(j<=right&&k<length){
res[k]=matrix[i][j];
k++;
j++;
}
up++;
i=up;
j=right;
while(i<=down&&k<length){//往下
res[k]=matrix[i][j];
k++;
i++;
}
right--;
i=down;
j=right;
while(j>=left&&k<length){//往左
res[k]=matrix[i][j];
k++;
j--;
}
down--;
i=down;
j=left;
while(i>=up&&k<length){//往上
res[k]=matrix[i][j];
k++;
i--;
}
left++;
i=up;
j=left;
}
*returnSize=length;
return res;
}
1. 两数之和
用了一个qsort,c自带的快排函数
struct Node{
int index;
int power;
};
int cmp(const void *a,const void *b){
return (*(struct Node *)a).power - (*(struct Node *)b).power;//a-b从小到大排序b-a则为从大到小排序
}
int* twoSum(int* nums, int numsSize, int target, int* returnSize){//双指针走起,哎,需要排序
int i,l=0,r=numsSize-1;
int mid=0;
int *res=(int *)malloc(sizeof(int)*2);
struct Node *nodes=(struct Node *)malloc(sizeof(struct Node)*numsSize);
for(i=0;i<numsSize;i++){
nodes[i].index=i;
nodes[i].power=nums[i];
}
qsort(nodes,numsSize,sizeof(struct Node),cmp);//索引绑定已就绪,排序没起作用
while(l<r){
if((nodes[l].power+nodes[r].power)==target){
res[0]=nodes[l].index;
res[1]=nodes[r].index;
*returnSize=2;
return res;
}else if((nodes[l].power+nodes[r].power)<target)
l++;
else
r--;
}
*returnSize=2;
return 0;
}
66. 加一
一遍AC,现在自己解题的时候,也记得要考虑多种情况了。
int* plusOne(int* digits, int digitsSize, int* returnSize){
int *res=(int *)malloc(sizeof(int)*(digitsSize+1));
int j=digitsSize-1,carry=1;
for(j=digitsSize-1;j>=0;j--){
digits[j]=digits[j]+carry;
if(digits[j]>=10){
carry=1;
digits[j]=digits[j]-10;
}
else
carry=0;
res[j+1]=digits[j];
}
if(carry==1){//最高位的进位
res[0]=1;
*returnSize=digitsSize+1;
}
else{
res=res+1;
*returnSize=digitsSize;
}
return res;
}
1356. 根据数字二进制下 1 的数目排序
排序用了很Low的冒泡
int* sortByBits(int* arr, int arrSize, int* returnSize){//count记录每个数字包含1的个数
int i,j,temp;
int *count=(int *)malloc(arrSize*sizeof(int));
memset(count,0,arrSize*sizeof(int));
int *arr1=(int *)malloc(arrSize*sizeof(int));
memset(arr1,0,arrSize*sizeof(int));
memcpy(arr1,arr,sizeof(int)*arrSize);
for(i=0;i<arrSize;i++){
while(arr1[i]>0){
temp=arr1[i]%2;
if(temp==1)
count[i]++;
arr1[i]=arr1[i]/2;
}
}
for (i=0;i<arrSize-1;i++){
bool flag=false;
for (j=0;j<arrSize-1-i;j++){
if (count[j] >count[j+1] || (arr[j]>arr[j+1]&&count[j]==count[j+1])){
temp = count[j];
count[j] = count[j+1];
count[j+1] = temp;
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
flag=true;
}
}
if(flag==false)
break;
}
(*returnSize)=arrSize;
free(count);
free(arr1);
return arr;
}
}
349. 两个数组的交集
放两个版本,当然是先放最新的咯,看看自己最开始写的,觉得蠢得不行。
所以遇到数组题,先想想排序吧
int cmp(const void *a,const void *b){
return (*(int *)a) - (*(int *)b);//a-b从小到大排序b-a则为从大到小排序
}
int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
//写数组题,一般都要先进行排序处理
if (!nums1 || !nums2) {
*returnSize = 0;
return NULL;
}
int *res=(int *)malloc(sizeof(int)*(nums1Size<nums2Size? nums1Size:nums2Size));
int i,j,count=0;//分别用于遍历数组nums1和数组nums2
qsort(nums1,nums1Size,sizeof(int),cmp);
qsort(nums2,nums2Size,sizeof(int),cmp);
for(i=0,j=0;i<nums1Size&&j<nums2Size;){
if(nums1[i]<nums2[j]){
i++;
}else if(nums1[i]>nums2[j]){
j++;
}else{
res[count++]=nums1[i];
i++;
j++;
if(count>1&&res[count-1]==res[count-2])
count--;
}
}
*returnSize=count;
res = (int *)realloc(res, count* sizeof(int));//扩内存的时候慎用,这是缩内存,所以还行
return res;
}
int* intersection(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){
int i,j,k=0,temp;
if(nums2Size>nums1Size)
temp=nums2Size;
else
temp=nums1Size;
int *result=(int *)malloc(sizeof(int)*temp);
memset(result,0,sizeof(int)*temp);
for(i=0;i<nums1Size;i++){
for(j=0;j<nums2Size;j++){
if(nums1[i]==nums2[j]){//没有判断result里的数是否重复
result[k]=nums1[i];
k++;
break;
}
}
}
for (i=0;i<k;i++){
for (j=0;j<k-1-i;j++){
if (result[j] > result[j+1]){
temp = result[j];
result[j] = result[j+1];
result[j+1] = temp;
}
}
}
if(k==0){
(*returnSize)=0;
return result;
}else{
for(i=0,j=1;j<k;j++)//我的天,用的这个删除重复数字的方法,要求是有序的。半天了才发现,呜呜呜
if(result[i]!=result[j])
result[++i]=result[j];
(*returnSize)=i+1;
return result;
}
}
26. 删除排序数组中的重复项
这题的思维和上一题的第二版中我用的那个排序方法是一样的
int removeDuplicates(int* nums, int numsSize){//双指针,前提是有序,这题已经有序了
int i=0,j;//i为新数组的下标
if(numsSize==0)
return 0;
for(j=0;j<numsSize;j++){
if(nums[j]!=nums[i])
nums[++i]=nums[j];
}
return i+1;
}