一、消失的数字
![](https://i-blog.csdnimg.cn/blog_migrate/0aabdade500ed9c3a6508a7ca5f89888.png)
思路一:
int missingNumber(int* nums, int numsSize)
{
int x = 0;
int i = 0;
for(i=0;i<=numsSize;i++)
{
x^=i;
}
for(i=0;i<numsSize;i++)
{
x^= (*(nums+i));
}
return x;
}
思路二
int missingNumber(int* nums, int numsSize)
{
int sum = 0;
int i = 0;
for(i=0;i<=numsSize;i++)
{
sum += i;
}
for(i=0;i<numsSize;i++)
{
sum -=nums[i];
}
return sum;
}
二、轮转数组
思路一
因为时间复杂度太大,导致运行时间超载,不建议使用这个思路
void rotate(int* nums, int numsSize, int k) {
k = k%numsSize;
for(k;k>0;k--)
{
int tmp = nums[numsSize-1];
for(int i=numsSize-1;i>0;i--)
{
nums[i] = nums[i-1];
}
nums[0] = tmp;
}
printf("%s",nums);
}
思路二
时间复杂度O(n)空间复杂度O(n)
void rotate(int* nums, int numsSize, int k) {
k = k % numsSize;
int newnums[numsSize];
int j = 0;
for(int tail = numsSize - k; tail <= numsSize - 1; tail++) {
newnums[j] = nums[tail];
j++;
}
for(int head = 0; head < numsSize - k; head++) {
newnums[j] = nums[head];
j++;
}
for(int i = 0; i < numsSize; i++) {
nums[i]=newnums[i];
}
}
思路三
时间复杂度O(n),空间复杂度O(1)
//逆置函数
void reverse(int* arr,int n)
{
int left,right,tmp;
left = 0;
right = n-1;
while(left<right)
{
tmp = arr[right];
arr[right]=arr[left];
arr[left] = tmp;
left++;
right--;
}
}
void rotate(int* nums, int numsSize, int k)
{
k = k%numsSize;//防止出现负数
reverse(nums,numsSize-k);//先逆置前面的
reverse(nums+numsSize-k,k);
reverse(nums,numsSize);
}
三、删除有序数组的重复项
思路
int removeDuplicates(int* nums, int numsSize){
int* p=nums;
int* tail=nums;
int tmp;
int count=0;
tmp=nums[0];
for(int i=0;i<numsSize;i++)
{
if(tmp!=(*p))
{
tmp=(*p);
tail++;
(*tail)=tmp;
count++;
}
p++;
}
// for(int j = 0;j<=count;j++)
// {
// printf("%d",nums[j]);
// }
return count+1;
}
四、返回倒数第k个节点
思路一
时间复杂度O(n)空间复杂度O(1)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode list;
int kthToLast(struct ListNode* head, int k)
{
list* p=head;
list* pp=head;
int count=0;
while(p)
{
count++;
p=p->next;
}
int end = count - k;
while(end--)
{
pp=pp->next;
}
return pp->val;
}
思路二
时间复杂度O(n)空间复杂度O(1)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode list;
int kthToLast(struct ListNode* head, int k)
{
if(head==NULL)
{
return head;
}
list* n1,*n2,*n3;
n1=NULL;
n2=head;
n3=head;
//逆置
while(n2)
{
n3=n3->next;
n2->next=n1;
n1=n2;
n2=n3;
}
while(--k)
{
n1=n1->next;
}
return n1->val;
}
五、链表的回文结构
思路很简单主要是对中间节点的寻找和对中间节点以后的链表进行逆置然后比较大小
下面的代码我就不写全就用函数调用来表示
class PalindromeList {
public:
bool chkPalindrome(ListNode* A) {
// write code here
ListNode* mid=middleNode(A);//中间节点
ListNode* rmid=reverseList(mid);//逆置
while(A&&rmid)
{
if(A->val!=rmid->val)
{
return false;
}
A =A->next;
rmid = rmid->next;
}
return true;
}
};
六、相交链表
思路
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode list;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{
list* pA=headA;
list* pB=headB;
int countA=1;
int countB=1;
while(pA->next)
{
pA=pA->next;
countA++;
}
while(pB->next)
{
pB=pB->next;
countB++;
}
if(pA!=pB)
{
return NULL;
}else{
//判断谁大
if(countA>=countB)
{
int a=countA-countB;
while(a--)
{
headA=headA->next;
}
while(headA!=headB)
{
headA=headA->next;
headB=headB->next;
}
return headA;
}else
{
int b=countB-countA;
while(b--)
{
headB=headB->next;
}
while(headA!=headB)
{
headA=headA->next;
headB=headB->next;
}
return headA;
}
}
}
上面是我自己写的代码过于冗余,下面的会好很多
typedef struct ListNode list;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{
list* pA=headA;
list* pB=headB;
int countA=1;
int countB=1;
while(pA->next)
{
pA=pA->next;
countA++;
}
while(pB->next)
{
pB=pB->next;
countB++;
}
if(pA!=pB)
{
return NULL;
}
int gap=abs(countA-countB);
list* longList = headA;
list* shortList = headB;
if(countB>countA)
{
longList=headB;
shortList=headA;
}
while(gap--)
{
longList=longList->next;
}
while(longList!=shortList)
{
longList=longList->next;
shortList=shortList->next;
}
return longList;
}
七、环形链表
再使用快慢指针的时候一定要注意
- 栈溢出
- 是否为空节点
typedef struct ListNode list;
bool hasCycle(struct ListNode *head)
{
list* fast,*slow;
fast=slow=head;
//单链表一个节点判断一下
if(head==NULL||head->next==NULL)
{
return false;
}
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(fast==slow)
{
return true;
}
}
return false;
}
八、环形链表②
typedef struct ListNode list;
struct ListNode *detectCycle(struct ListNode *head) {
list*fast,*slow;
fast=slow=head;
if(head==NULL||head->next==NULL)
{
return NULL;
}
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(slow==fast)
{
break;
}
}
if(slow==fast)
{
//如果不相等就一直循环
while(head!=slow)
{
head=head->next;
slow=slow->next;
}
//相等后跳出循环
return head;
}
return NULL;
}
思考:如果slow走一步,fast走三步,一定会相遇吗?会不会错开
一定会相遇
九、随机链表的复制
步骤
![](https://i-blog.csdnimg.cn/blog_migrate/bd4565ddaeae058947d93a9858a2621f.png)
typedef struct Node Node;
struct Node* copyRandomList(struct Node* head) {
Node* cur = head;
//拷贝节点插入原节点的后面
while(cur)
{
Node* copy = (Node*)malloc(sizeof(Node));
copy->val = cur->val;
//插入
copy->next = cur->next;
cur->next = copy;
//迭代
cur = cur->next->next;
}
//控制拷贝节点的random
cur = head;
while(cur)
{
Node* copy = cur->next;
if(cur->random == NULL)
{
copy->random = NULL;
}
else
{
copy->random = cur->random->next;
}
//迭代
cur = cur->next->next;
}
//把copy节点解下来,链接成新的链表
Node* copyhead = NULL,*tail = NULL;
cur = head;
while(cur)
{
Node* copy = cur->next;
Node* next = copy->next;
//尾插
if(tail == NULL)
{
copyhead = tail = copy;
}
else
{
tail->next = copy;
tail = tail->next;
}
cur->next =next;
cur = next;
}
return copyhead;
}