1.
要找俩个数使其相加等于一个数,那么俩个数从头尾出发,先动一边,假设是尾先动,一开始俩个数相加大于sum(小于的话就动头),那么总有一时刻俩数相加小于sum,则就在那一刻停下来,然后动头那一边去逼近sum,最坏情况就是俩个数字相遇了,时间复杂度就为O(N)
2.
可以通过一直替换T(n-1)使其变成常数,每次降低一次就为有里面减一到外面来,因为时间复杂度看的是最大级,所以是0(N)
3 .
思路一:
在开俩个数组去存放数据,一个存放k个,一个存放numsSize-k个,先把它们分隔开,然后再都放进原来的数组里,就可以达到要求
代码实现:
void rotate(int* nums, int numsSize, int k) {int k1=k%numsSize;int* a=(int*)malloc(sizeof(int)*(numsSize-k1));int* b=(int*)malloc(sizeof(int)*k1);for(int i=0;i<numsSize-k1;i++){a[i]=nums[i];}for(int j=0;j<k1;j++){b[j]=nums[numsSize-k1+j];}for(int z=0;z<k1;z++){nums[z]=b[z];}for(int t=0;t<numsSize-k1;t++){nums[t+k1]=a[t];}
}
思路二:
先转置整个数组数字,然后在转置k-1个元素,最后转置k到numsSize的数组数字,这样就调换了以k分成俩边数组的位置
代码实现:
void reverse(int* nums, int begin, int end)
{while (begin < end){int tmp = nums[begin];nums[begin] = nums[end];nums[end] = tmp;++begin;--end;}
}// 三趟逆置倒的思路
void rotate(int* nums, int numsSize, int k) {if (k > numsSize){k %= numsSize;}reverse(nums, 0, numsSize - 1);reverse(nums, 0, k - 1);reverse(nums, k, numsSize - 1);
}
4.
思路:
要找到确失的数字,可以把这个数全部加起来,然后再重新创建一个不却数字的数组,把这个也加起来,然后俩个相减,得到值就是缺少的值
代码实现:
int missingNumber(int* nums, int numsSize){int b=0;int c=0;int* a=(int*)malloc(sizeof(int)*(numsSize+1));for(int i=0;i<=numsSize;i++){a[i]=i;}for(int i=0;i<numsSize;i++){b+=nums[i];}for(int i=0;i<=numsSize;i++){c+=a[i];}return c-b;
}
5.
思路一:
总数-k为正数第几个,把总数算出来在和k相减就可以知道在哪一个位置
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/
int gettree(struct ListNode* head)
{int size=0;while(head){head=head->next;size++;}return size;
}int kthToLast(struct ListNode* head, int k){struct ListNode* cur=head;int a=gettree(head);int c=a-k;while(c--){cur=cur->next;}return cur->val;
}
思路二:
快慢指针,先让fast走k步后,让fast和slow一起走,slow一共会走(总数-k)步,也可以走到对应位置
class Solution {
public:ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {struct ListNode* slow = pListHead;struct ListNode* fast = slow;while (k--){if (fast)fast = fast->next;elsereturn NULL;}while (fast){slow = slow->next;fast = fast->next;}return slow;}
};
6.
思路 1:
快慢指针,先找到中间结点,然后逆置中间后面的结点,最后跟前半部分对比
代码实现:
这一步是找中间结点
while(fast&&fast->next){slow=slow->next;fast=fast->next->next;}
这一步是逆置中间后面的结点,然后把连接方向改变
ListNode* cur=NULL;ListNode* next=A;while(slow){next=slow->next;slow->next=cur;cur=slow;slow=next;}
把前半部分和后半部分进行对比
next=A;while(cur){if(next->val!=cur->val){return false;}next=next->next;cur=cur->next;}return true;
总代码:
/*
struct ListNode {int val;struct ListNode *next;ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:bool chkPalindrome(ListNode* A) {ListNode* fast=A;ListNode* slow=A;while(fast&&fast->next){slow=slow->next;fast=fast->next->next;}ListNode* cur=NULL;ListNode* next=A;while(slow){next=slow->next;slow->next=cur;cur=slow;slow=next;}next=A;while(cur){if(next->val!=cur->val){return false;}next=next->next;cur=cur->next;}return true;}
};
思路二:
可以把值都放进数组里面,但是如果题目没告诉链表最大值就不能使用这个方法
放进数组后,把头尾的值取出来进行对比,一直往中间
代码实现:
class PalindromeList {
public:bool chkPalindrome(ListNode* A) {// write code hereint a[900] = { 0 };ListNode* cur = A;int n = 0;//保存链表元素while (cur){a[n++] = cur->val;cur = cur->next;}//判断数组是否为回文结构int begin = 0, end = n - 1;while (begin < end){if (a[begin] != a[end])return false;++begin;--end;}return true;}
};
7.
思路:
因为俩个链表长度有可能不一样长,所以需要让长的链表先走,使得出发时俩个俩个链表等长, 就可以找到最后一个相等的结点(不是找第一个相等的而是找最后一个)
代码实现:
计算俩个链表计数
int a=0;int b=0;struct ListNode* aa=headA;struct ListNode* bb=headB;while(aa){a++;aa=aa->next;}while(bb){b++;bb=bb->next;}
找到俩个链表的长的哪一个,可以用假设法,可以节省很多步骤,先假设1大2小,不是就调整,非常方便
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {int a=0;int b=0;struct ListNode* aa=headA;struct ListNode* bb=headB;while(aa){a++;aa=aa->next;}while(bb){b++;bb=bb->next;}int c=a-b>0?a-b:b-a;struct ListNode* long1=headA;struct ListNode* short1=headB;if(a<b){long1=headB;short1=headA;}while(c--){long1=long1->next;}while(short1&&long1){if(short1==long1){return long1;}else{long1=long1->next;short1=short1->next;}}return NULL;
}
8.
思路:
因为要复制出一个与原链表一样的东西出来,所以可以在每个结点后面跟一个新结点
代码实现:
1.创建新结点连在原链表的后面,并把val值也复制过去
struct Node* cur=head;while(cur){struct Node* copy=(struct Node*)malloc(sizeof(struct Node));copy->val=cur->val;copy->next=cur->next;cur->next=copy;cur=copy->next;}
2 .把random的也复制过去
cur=head;struct Node* copyhead=NULL;struct Node* copytail=NULL;while(cur){struct Node* copy=cur->next;struct Node* next=copy->next;if(cur->random==NULL){copy->random=NULL;}else{copy->random=cur->random->next;}cur=next;}
3.把复制的链表从原链表上拆下来
cur=head;while(cur){struct Node* copy=cur->next;struct Node* next=copy->next;if(copytail==NULL){copyhead=copytail=copy;}else{copytail->next=copy;copytail=copytail->next;}cur->next=next;cur=next;}return copyhead;
/*** Definition for a Node.* struct Node {* int val;* struct Node *next;* struct Node *random;* };*/struct Node* copyRandomList(struct Node* head) {struct Node* cur=head;while(cur){struct Node* copy=(struct Node*)malloc(sizeof(struct Node));copy->val=cur->val;copy->next=cur->next;cur->next=copy;cur=copy->next;}cur=head;struct Node* copyhead=NULL;struct Node* copytail=NULL;while(cur){struct Node* copy=cur->next;struct Node* next=copy->next;if(cur->random==NULL){copy->random=NULL;}else{copy->random=cur->random->next;}cur=next;}cur=head;while(cur){struct Node* copy=cur->next;struct Node* next=copy->next;if(copytail==NULL){copyhead=copytail=copy;}else{copytail->next=copy;copytail=copytail->next;}cur->next=next;cur=next;}return copyhead;
}