文章目录
1.数组oj
2.链表oj
文章内容
1.数组oj
1. 原地移除数组中所有的元素值为val,要求时间复杂度为O(N),空间复杂度为O(1)。力扣
int removeElement(int* nums, int numsSize, int val){
int k = numsSize;
int a = 0;
int b = 0;
while(b<k)
{
if(nums[b] != val)
{
nums[a] = nums[b];
a++;
b++;
}
else
{
b++;
}
}
return a;
}
2. 删除排序数组中的重复项。力扣
int removeDuplicates(int* nums, int numsSize){
int src = 1;
int dest = 0;
while(src < numsSize)
{
if(nums[src] == nums[dest])
{
src++;
}
else
{
dest++;
nums[dest] = nums[src] ;
src++;
}
}
return dest+1;
}
3. 合并两个有序数组。力扣
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
int end1 = m-1;
int end2 = n-1;
while(end1>=0 && end2>=0)
{
if(nums1[end1] > nums2[end2])
{
nums1[nums1Size-1] = nums1[end1];
end1--;
nums1Size--;
}
else
{
nums1[nums1Size-1] = nums2[end2];
end2--;
nums1Size--;
}
}
while(end2>=0)
{
nums1[nums1Size-1] = nums2[end2];
end2--;
nums1Size--;
}
//return nums1;
}
2.链表oj
1. 删除链表中等于给定值 val 的所有结点。力扣
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode* prve = NULL;
struct ListNode* cur = head;
while(cur)
{
if(cur->val == val)
{
if(cur == head)
{
head = cur->next;
free(cur);
cur = head;
}
else
{
prve->next = cur->next;
free(cur);
cur=prve->next;
}
}
else{
prve = cur;
cur = cur->next;
}
}
return head;
}
2. 反转一个单链表。力扣
方法一:
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* newhead = NULL;
struct ListNode* cur = head;
while(cur)
{
struct ListNode* after = cur->next;
//头插
cur->next = newhead;
newhead = cur;
cur = after;
}
return newhead;
}
方法二:
思维图
struct ListNode* reverseList(struct ListNode* head){
struct ListNode* n1,* n2,* n3;
n1 = NULL;
n2 = head;
if(n2)
{
n3 = n2->next;
}
while(n2)
{
n2->next = n1;
//往后走
n1 = n2;
n2 = n3;
if(n3)
{
n3 = n3->next;
}
}
return n1;
}
3. 给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则
返回第二个中间结点。力扣
4. 输入一个链表,输出该链表中倒数第k个结点。链表中倒数第k个结点_牛客题霸_牛客网
本题思路与上一题类似。
struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
// write code here
struct ListNode* fast = pListHead;
struct ListNode* slow = pListHead;
while(k--)
{
if(fast == NULL)
{
return NULL;
}
fast = fast->next;
}
while(fast)
{
slow=slow->next;
fast=fast->next;
}
return slow;
}
5. 将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有
结点组成的。力扣
6. 编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结
点之前 。链表分割_牛客题霸_牛客网
class Partition {
public:
ListNode* partition(ListNode* pHead, int x) {
// write code here
struct ListNode* phead = pHead;
struct ListNode * lesshead,*lesstail,*greaterhead,*greatertail;
lesshead = lesstail = (struct ListNode*)malloc(sizeof(struct ListNode));
greaterhead = greatertail = (struct ListNode*)malloc(sizeof(struct ListNode));
while(phead)
{
if(phead ->val < x)
{
lesstail ->next = phead;
lesstail = lesstail->next;
}
else
{
greatertail ->next = phead;
greatertail = greatertail->next;
}
phead= phead->next;
}
lesstail->next = greaterhead->next;
free(greaterhead);
struct ListNode* head = lesshead->next;
free(lesshead);
greatertail->next = NULL;
return head;
}
};
7. 链表的回文结构。链表的回文结构_牛客题霸_牛客网
本题需要用到查找中间节点,和逆置链表,这两项,上述内容都有
struct ListNode* middleNode(struct ListNode* head) {
struct ListNode* slow = head, * fast = head;
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
struct ListNode* reverseList(struct ListNode* head)
{
struct ListNode* newnode = NULL;
struct ListNode* cur = head;
while (cur)
{
struct ListNode* after = cur->next;
//头插
cur->next = newnode;
newnode = cur;
cur = after;
}
return newnode;
}
class PalindromeList {
public:
bool chkPalindrome(ListNode* head)
{
// write code here
struct ListNode * mid = middleNode(head);
struct ListNode * rmid = reverseList(mid);
while(rmid && head)
{
if(rmid->val != head->val)
{
return false;
}
rmid = rmid->next;
head= head->next;
}
return true;
}
};
8. 输入两个链表,找出它们的第一个公共结点。力扣
故本题的思路就是先计算出两个链表的长度,之后让长的链表先走差值步。之后两个链表一起走,如果两个链表遍历到最后都没有公共节点,那么说明两个链表不相交。
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
struct ListNode* cura = headA,*curb = headB;
int len1 = 0;
int len2 = 0;
while(cura)
{
cura = cura->next;
++len1;
}
while(curb)
{
curb = curb->next;
++len2;
}
int gab = abs(len1-len2);
if(len1>len2)
{
while(gab--)
{
headA = headA ->next;
}
while(headA != headB && headA && headB)
{
headA = headA->next;
headB = headB->next;
}
if(headA == NULL)
{
return NULL;
}
return headA;
}
else
{
while(gab--)
{
headB = headB ->next;
}
while(headA != headB && headA && headB)
{
headA = headA->next;
headB = headB->next;
}
if(headA == NULL)
{
return NULL;
}
return headA;
}
}
9. 给定一个链表,判断链表中是否有环。力扣
这到题的思路还是用快慢指针的思想来,快指针走两步,慢指针走一步,如果有环,快指针是回追上慢指针的。
bool hasCycle(struct ListNode *head) {
struct ListNode* slow = head,*fast = head;
while(fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if(slow == fast)
{
return true;
}
}
return false;
}
10. 给定一个链表,返回链表开始入环的第一个结点。 如果链表无环,则返回 NULL力扣
快指针每次走两步,满指针每次走一步,每次差1步,当链表中有环,快指针肯定能追上满指针
这是为什么呢?
快指针走其他步呢?
有了以上的基础性分析,我们接下来再进行分析:
上图第一句话是 “右侧分析是典型的错误”!!!
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode* slow = head ,*fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
if(slow == fast)
{
struct ListNode* meet = slow;
while(head != meet)
{
meet = meet->next;
head = head->next;
}
return meet;
}
}
return NULL;
}