每日一刷--LeetCode

2018.8.30    Q26.

①C语言求数组a的长度,常用方法是sizeof(a)/sizeof(a[0])。

但若是通过传递数组名参数到子函数中,就不可以这样获得数组长度。因为 a是函数参数,到了子函数中就是一个指针了,而系统运行时是不知道该指针指向的地址占多大空间的。所以如果子函数内部需要用到数组长度,应该将其作为参数与数组一起传入。https://zhidao.baidu.com/question/263663984320559685.html

②数组为空长度为0的情况需要单独考虑。

2018.8.31    Q189

①数组声明时,可以使用一个已经声明了的变量来定义长度:int tmp[k];

②要考虑操作数的大小超过数组长度的情况。

解法一:

void rotate(int* nums, int numsSize, int k) {
    if(numsSize<1||k<1){
        return;
    }
    int i=0, tmp[k];
    k=k%numsSize;
    for(i=0;i<k;i++){
        tmp[i]=nums[numsSize-k+i];
    }
    for(i=numsSize-k-1;i>=0;i--){
        nums[i+k]=nums[i];
    }
    for(i=0;i<k;i++){
        nums[i]=tmp[i];
    }
}

解法二: 2018.9.1

void rotate(int* nums, int numsSize, int k) {
    if(numsSize<1||k<1){
        return;
    }
    int i=0, j=0, tmp[k];
    k=k%numsSize;
    for(i=0;i<k;i++){
        tmp[i]=nums[numsSize-k+i];
    }
    for(i=0;i<k;i++){
        for(j=numsSize-1-i-k; j>=0;j=j-k){
            nums[j+k]=nums[j];
        }
    }
    for(i=0;i<k;i++){
        nums[i]=tmp[i];
    }
    return;
}

在用解法二时,不知什么时候把 int tmp[k]; 语句放到 k = k%numsSize; 之后了,结果一直报错说 数组的长度绑定了个非整数k。懵逼了好久,后来才反应过来,1对1取余的结果是0 而不是1,所以一当numsSize和k相等时,k就成了0,一声明数组可不就成了非正数的长度。

 

2018.9.2    Q217

解出来并不难,但用时太长(1861ms),寻找一下更快的办法。

不知为何想到了常用的排序算法,能不能先排好序再遍历一遍?查了查,C语言提供了一个快速排序的库函数 qsort() ,采用这种思路解题,果然用时变得很短(32ms)。下面是对 qsort() 的介绍:

①void  qsort() 在stdlib.h 函数库里,采用了快速排序算法的思想,返回值为空。

②函数参数共4个,为( void* base,    int nelem,    int width,      int* (fcom) (const void* , const void*),各参数的含义分别为:

(void * 待排序的数组的首地址,    int 数组长度,        int 单个元素的大小(可用sizeof(a[0])计算),

定义排序顺序的函数名称)

③ 需要另外单独定义一个函数,用于确定是递增排序还是递减排序。若分别命名为compInc(递增)和compDec(递减),则函数应定义为:

int compInc(const void* a, const void* b){
    return *(int*) a - *(int*) b;
}



int compDes(const void* a, const void* b){
    return *(int*) b - *(int*) a;
}

 

2018.9.3  Q122

第一次看到题目时感觉很复杂,产生了畏难心理,放了好几天才做。“怎么编程才能解出题?人怎么想,就让计算机怎么想,不要怕难”。

理了理思路,写了第一版出来。因为用到了递归,所以在参数传递时用到了数组的传递方法——若函数参数列表为 function(void * a,……),有一个数组nums[] = {1,2,3,4,5,6},那么当想把nums传到函数里时,应该在数组名前加取地址符号:function(&a[0], ……)。

目前题目的测试用例里都有一个很长很复杂的测试样例,递归的思路在解该测试用例时超时了,想想怎么用循环解决。

在将思维转化成代码的过程中,有一些直觉用了的思路后来发现都是合理的,所以要勤加练习,多整理思路,珍惜之前的直觉。

 

2018.9.10   

又想了很久没想明白,心态崩了,就百度了下答案。不考虑别人提到的什么贪心算法、最大连续子数组和之类的,我们就题论题。别人的代码是这样的思想:从第二天开始逐天检查,若今天比昨天价高,那就昨天买今天卖(实际上也就是贪心算法,不考虑以后,不考虑全局最优)。这其中隐含了一条:允许在同一天先卖后买——例如D1买、D2卖、D2买、D3卖,【利润=(D2-D1)+(D3-D2)=D3-D1】,其实就相当于是D1买、D3卖,因为操作的连续性,局部最优最后产生的结果就是全局最优。

而之前自己在考虑的时候是认为不允许的,所以一直在想怎么才能找到 能得到最大收益的买卖时间,从而弄得很复杂。之前想到的、用于确定某一天要不要买入的tips(若第 n 天价格低于第 n+1 天,则第 n 天必买入)其实也是这个道理。

 

2018.9.3   Q136

线性时间复杂度:O(n logn)算线性。

 

2018.9.4(2018.9.8补)   Q1

没有规定一定是正数,所以直接看两数之和是不是target ,不应该假定 这个数大于target就不行。

速度有点慢,可以看看有没有更好的办法。

 

2018.9.5+9.7   Q350

malloc() 的用法:有个数组int a, 给其分配内存: a = (int *)malloc (数组大小)   ;      malloc()的返回值是void * 类型,要强制类型转换。

编译出错了:Line 17: load of null pointer of type 'int'。         17行是:if(nums1[i]<nums2[j]); 真的不明白错在了哪哭,,,,,

----------------是因为往 qsort 里传数组的时候,传的是&nums1而不是nums1,导致出错。错误的原因还是没弄清楚数组和指针的关系,自己下去再捋捋。

改正上面问题后,有一个测试用例没通过:数组一 [-2147483648,1,2,3]  和数组二  [1,-2147483648,-2147483648],程序的输出结果只有 1 没有 -2147483648。看了下输出,发现 qsort() 排序后把 -2147483648 排在了最后,说明 qsort认为它是最大的。但后来比较的时候 它还是小于2。

换了方法,用了常规思路,设置一个数组作为 tag,逐个比较,AC了并且速度很快,因为先比较了两个数组谁长谁短,然后遍历短的。

 

2018.9.6    Q66

加1要考虑到进位操作,以及长度变长后的数字后移。

最大的收获是明确了传入参数 int * returnSize 的作用:  C语言中,数组长度是必须和数组同时出现的(因为数组名只是一个指针,指向数组的起始地址,若没有数组长度,则有可能会产生非法地址的操作)。而函数返回值已经是数组了,就需要另外的方法来将本数组的长度告知主函数——主函数申请一个指针 returnSize 指向某个地址,由于是主函数申请的,所以只要在主函数的生存周期内,该地址均合法有效。主函数将该指针传递到子函数中,也就相当于把这个地址告知给子函数,子函数将数组长度存放在这个指针指向的地方,那么即使当子函数生存周期结束时,该地址内的数据仍然有效,从而将数组长度传递给了主函数。

 

2018.9.8    Q283

没什么大问题,按正常思路做就行。

2018.9.8    Q36

本题涉及到了二维数组、char类型和ASCII码,逐条列出:

①二维数组的行坐标和列坐标与 i 、j 之间的关系需要捋清楚。横着扫描就是 [ i ] [ j ] ,竖着扫描就是 [ j ] [ i ],若是像数独单元格一样,一块一块扫描,则是 [ (i/3) *3 + j/3 ] [ (i%3) *3 + j%3 ],最后这点可以再想想清楚。

②注意到题目给的数组输入类型是char **,但里面存的是数字,有可能会忘记 char 和 int 的一个转换。 char 类型是以ASCII 码的方式存着的,数字0的ASCII 码是48,因此可以直接通过 char [ i ][ j ] - 48 转换成 int 型的数字进行下一步操作。

③在判断某一数字是否出现两次时,我是设置了一个标志数组,哪一个数字出现过,就把对应位置上的数字置为1。数组长度在定义时要注意比数字个数多一个,这样就可以不用对 i 进行减一的操作了。

 

2018.9.9    Q48

本题最基础的解法就是重新申请一个数组,逐行旋转至新数组中。

但题目要求在原地旋转,那么就按人脑旋转数组的思路来分析。从里到外逐圈旋转、先保存该圈的第一列,再挪动各元素、将第一列归位至第一行。其中在挪动各元素时,可以将各元素的坐标列出,总结规律。提交后发现速度非常快(用时0ms),可以算是找到了最简捷的解法。

 

2018.9.11(2018.9.12补)    Q387

字符串是以ASCII 码存储的,a - z的ASCII码为 97 - 122,采用的是以空间换时间的方法,时间复杂度O(n),空间复杂度O(1),但速度很慢只超过20%,之后可以想想有哪些更快速的办法。

 

2018.9.12    Q344

时间复杂度O(n),空间复杂度O(n);

字符串是以字符数组的形式存储的;声明字符串长度时,要在元素个数上+1,以留最后的位置存放 ‘ \0 ’(会自动存放,无需手动赋值)。

声明一个变量a,表示:在内存中标记了一块地方的名字为a,也就是说把这段内存所在的地址重命名为a;若声明了一个数组 a[ ],那么就意味着 数组的起始地址就叫 a。那么若有 char a[10]="hello";    char* b;则 b=a  等价于 b=&a[0] 。这并不是复制数组,只是让 b 也指向 a 指向的数组而已。

 

2018.9.12    Q242

时间复杂度O(n),空间复杂度O(1);  求字符串长度的函数 strlen(a);

进阶:先把各字母排序,再对比?!

 

2018.9.12    Q125

ASCII码:0-9对应48-57,A-Z 对应65-90,a-z对应97-122。

数字和大写字母之间也可能差32。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值