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;
else
return 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 here
int 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;
}