之前刷题总结:
因为之前刷的题回头看之后发现一些题仍然有很多问题,所以在以后刷题的时候自己会:
- 一遍就能做出来的题自己就可以不用二刷,所以刷题归为两类。
- 自己完全没有思路,代码也写不出来的题,自己需要二刷。甚至是三刷,然后继续做总结。
- 写题解,配合画图理解,让自己每一步骤都弄清楚之后才是真正的吃透了这个题。
- 刷题必须要坚持和连续,一日不练三日空。
- 刷题的时候,应该回想之前刷题出现的类似问题和解题方法,看能不能复用一些方法模块来解决问题。
- 在原来的基础之上自己去优化代码,或者另外写方法来解决问题。
- 349. 两个数组的交集 - 力扣(LeetCode)
- 打印从1到最大的n位数_牛客题霸_牛客网 (nowcoder.com)
- 计算日期到天数转换_牛客题霸_牛客网 (nowcoder.com)
- 尼科彻斯定理_牛客题霸_牛客网 (nowcoder.com)
- 645. 错误的集合 - 力扣(LeetCode)
- 密码检查_牛客题霸_牛客网 (nowcoder.com)
- 数字在升序数组中出现的次数_牛客题霸_牛客网 (nowcoder.com)
- . - 力扣(LeetCode)
- . - 力扣(LeetCode)
- . - 力扣(LeetCode)
- 图片整理_牛客题霸_牛客网 (nowcoder.com)
- 724. 寻找数组的中心下标 - 力扣(LeetCode)
- 字符个数统计_牛客题霸_牛客网 (nowcoder.com)
一:二刷:
(1):169. 多数元素 - 力扣(LeetCode)
题解:
int cmp(void* a,void* b)
{
return (*(int*)a - *(int*)b);
}
int majorityElement(int* nums, int numsSize) {
qsort(nums,numsSize,sizeof(int),cmp);
int count = 1;//因为数组是非空的,至少有一个元素
int tmp = nums[0];
for(int i = 1; i < numsSize; i++)
{
if(nums[i] == tmp)
{
count++;
}
else//重置计数器和交换容器值
{
count = 1;
tmp = nums[i];
}
if(count > numsSize/2)
{
return tmp;
}
}
return nums[0];
}
总结:
- 在查找代码错误的时候,经常注意的一个点:自己变量名写错字母顺序,还有一些其他的语法错误,应该在代码写完之后自己重新看检查一下语法。
- .在思考题目的时候,不要以自己的固有思维去写代码,应该实际根据自己整理出来的逻辑思维步骤去写代码,如果写出来不对也应该首先检查的是自己思路,或者具体的某些步骤不对(顺序不对还是什么不对)。
(2):728. 自除数 - 力扣(LeetCode)
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
// int* selfDividingNumbers(int left, int right, int* returnSize) {
// *returnSize = 0;
// int* arr = (int*)malloc(sizeof(int)*(right - left + 1));//因为是闭区间,所以要+1
// for(int i = left; i <= right; i++)
// {
// int flag = 1;
// int tmp = i;
// while(tmp)
// {
// int cur = tmp%10;
// if(cur==0 || i%cur!=0)
// {
// flag = 0;
// break;
// }
// tmp/=10;
// }
// if(flag)
// {
// arr[(*returnSize)++] = i;//arr[*returnSize++] = i这种写是不正确的,++的运算符优先级要高于*
// }
// }
// return arr;
// }
bool is_divid(int n)
{
int t = n;
while(t)
{
int tm = t%10;
if(tm == 0 || n%tm!=0)
{
return false;
}
t /= 10;
}
return true;
}
int* selfDividingNumbers(int left, int right, int* returnSize) {
int* arr = (int*)malloc(sizeof(int)*(right - left + 1));
*returnSize = 0;
for(int i = left; i <= right; i++)
{
if(is_divid(i))
{
arr[(*returnSize)++] = i;
}
}
return arr;
}
(3):142. 环形链表 II - 力扣(LeetCode)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *detectCycle(struct ListNode *head)
{
struct ListNode* fast = head,*slow = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(fast == slow)
{
struct ListNode* meet = head;
while(slow!=meet)
{
slow = slow->next;
meet = meet->next;
}
return meet;
}
}
return NULL;
}
题解:
这是个数学问题,以后再重新理解证明一遍
(4)141. 环形链表 - 力扣(LeetCode)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
bool hasCycle(struct ListNode *head) {
struct ListNode* fast = head,*slow = head;
while(fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if(fast == slow)
return true;
}
return false;
}
总结;
- 快慢指针:快指针走两步,慢指针走一步。快指针先进环,慢指针后进环,最后慢指针和快指针在环里面相遇。
- 慢指针和快指针一定能够在环里面相遇。
- 其他情况:快指针和慢指针走的步数不一样,快指针走奇数步,慢指针走偶数步,慢指针走偶数步快指针走奇数步,是否存在这些情况,存在这些情况的话快慢指针是否相遇?