力扣刷题记录2-29-2020-3-1

一、字符串轮转
力扣刷题记录2-29-2020-3-1_第1张图片

class Solution {
public:
    bool isFlipedString(string s1, string s2) {
        if(s1.size() != s2.size()) return false;
        if(s1.size() == s2.size() & s1.size() == 0) return true;

        string s3;
        s3 = s2;
        s3 += s2;
        int n;
        if(n = s3.find(s1) != string::npos)
            return true;
        else
            return false;
    }
};

总结:新增字符串为两个s2结合,如果s3中有s1子串就返回true;

二、移除链表重复节点
力扣刷题记录2-29-2020-3-1_第2张图片

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeDuplicateNodes(ListNode* head) {
        
        if(head == NULL || head->next == NULL) return head;

        //使用哈希表
        unordered_set<int>uSet;
        ListNode *rear = head->next;
        ListNode *prev = head;

        uSet.insert(head->val);
        while(rear)
        {
            if(!uSet.count(rear->val))
            {
                uSet.insert(rear->val);
                prev->next = rear;
                prev = prev->next;
            }
            rear = rear->next;
        }

        prev->next = NULL;

        return head;
        

    }
};

总结:本题中由于要删除重复的节点,所以我们很容易想到C++中hash表,就对弈STL unordered_set, 然后遍历链表,使用前后指针。有发现重复的元素就一直向前移动。当没有出现重复的元素时,前驱指针先移动,最后在后继指针next置空,这样可以处理尾结点以及防止某处后面全为重复节点

三、返回链表倒数第K个节点

力扣刷题记录2-29-2020-3-1_第3张图片

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    int kthToLast(ListNode* head, int k) {
        //双指针。先走K步,然后再让后驱跟前指针一起走。
        if(head == NULL) return 0;

        ListNode *prev = head;

        while(k)
        {
            prev = prev->next;
            k--;
        }

        while(prev)
        {
            head = head->next;
            prev = prev->next;
        }
        
        return head->val;
    }
};

总结:本题思路前后指针,前指针先走K,然后后指针(头)与前指针一起走,后指针到了K就前指针到了倒数第K个节点

四、删除链表某个节点

力扣刷题记录2-29-2020-3-1_第4张图片

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {
        
        if(node == NULL) return;

        ListNode *mov = node;
        ListNode *prev = mov->next;;
        
        while(prev)
        {
            mov->val = prev->val;
            if(prev->next != NULL) mov = mov->next;
            prev = prev->next;
        }
        mov->next = NULL;
    }
};

总结:使用两个指针一直后面值赋值到前面即可,注意mov不可走到尾节点

五、分割链表
力扣刷题记录2-29-2020-3-1_第5张图片

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* partition(ListNode* head, int x) {

        if(head == NULL || head->next == NULL) return head;
        
    //出题人语文是数学老师教的,按照题意的话,可以使用多的空间,以X为头,进行大于头插,小于尾插。

        //解法2:对链表进行分大小
        ListNode *bigHead = new ListNode(0);
        ListNode *littleHead = new ListNode(0);
        ListNode *tmp1 = bigHead;
        ListNode *tmp2 = littleHead;

        while(head)
        {
            //比较大小
            if(head->val >= x)
            {
                tmp1->next = head;
                tmp1 = tmp1->next;
            }
            else
            {
                tmp2->next = head;
                tmp2 = tmp2->next;
            }
            //头移动
            head = head->next;
        }

        //重组链表
        tmp2->next = bigHead->next;
        tmp1->next = NULL;

        return littleHead->next;


        

    }
};

总结:若遇到分类题目及可以使用双百法。还有另外一种思路,在注释中

六、链表求和

力扣刷题记录2-29-2020-3-1_第6张图片

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* addTwoNumbers(ListNode* L1, ListNode* L2) {

        if(L1 == NULL || L2 == NULL) return NULL;

        //要注意有进位的情况
        ListNode *head = new ListNode(0);
        head->next = NULL;
        ListNode *tmp = head;
        int sum;
        int num;
        int carryBit = 0;
        int v1, v2;
        //可能存在两个链表长度不相等的情况
        while(L1 != NULL || L2 != NULL)
        {
           v1 = (L1 == NULL) ? 0 : L1->val;
           v2 = (L2 == NULL) ? 0 : L2->val;

            //两数相加加进位
            sum = v1 + v2 + carryBit;
            num = sum > 9 ? (sum % 10) : sum;
            //取得进位
            carryBit = sum > 9 ? 1 : 0;
            ListNode *node = new ListNode(num);
            tmp->next = node;
            node->next = NULL;
            tmp = tmp->next;
            if(L1) L1 = L1->next;
            if(L2) L2 = L2->next;
        }

        //收尾处理
        if(carryBit == 1)
        {
            ListNode *node = new ListNode(carryBit);
            tmp->next = node;
            node->next = NULL;
        }

        return head->next;
    }
};

总结:直接相加,判断进位,最后结束要判断是否有进位。

七、回文链表
力扣刷题记录2-29-2020-3-1_第7张图片

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    bool isPalindrome(ListNode* head) {
        //找中间翻转再比较。学到了,找中间的方法,让前指针走两倍,后指针走一下
        //空串和1个位回文。。
        if(head == NULL || head->next == NULL) return true;

        ListNode *first = head;
        ListNode *slow = head;

        //快慢指针找中点
        while(first && first->next)
        {
            slow = slow->next;
            first = first->next->next;
        }
        //逆序前半段
        ListNode *cur = head;
        ListNode *tmp;

        while(cur->next != slow)
        {
            tmp = cur->next;
            cur->next = tmp->next;
            tmp->next = head;
            head = tmp;
        }
        //判断奇数偶数
        while(slow)
        {
            //偶数时
            if(first == NULL)
            {
                if(slow->val == head->val)
                {
                    head = head->next;
                    slow = slow->next;
                }
                else
                {
                    return false;
                } 
            }
            else if(first->next == NULL)
            {
                if(slow->next->val == head->val)
                {
                    head = head->next;
                    slow = slow->next;
                }
                else 
                {
                    return false;
                }
                
                if(slow->next == NULL)
                  break;
            }
        }
        
        return true;

    }
};

总结:找到中间位置,前后指针,一个走两个一个走一个,当前面的指针到达尾部就找到了中间位置。然后再进行翻转前面的链表。之后比较。

八、链表相交
力扣刷题记录2-29-2020-3-1_第8张图片

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if(headA == NULL || headB == NULL ) return NULL;

        ListNode *a = headA;
        ListNode *b = headB;
        //快慢指针
        while(a != b)
        {
          a = a == NULL ? headA : a->next;
          b = b == NULL ? headB : b->next;
        }

        return a;

    }
};

总结:双指针长度消差法

九、链表环路监测
力扣刷题记录2-29-2020-3-1_第9张图片

### 解题思路
此处撰写解题思路

### 代码

```cpp
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {

        //快慢指针
        if(head == NULL || head->next == NULL) return NULL;

        ListNode *fast = head;
        ListNode *slow = head;
        bool sign = false;
        while(fast && fast->next)
        {
            slow = slow->next;
            fast = fast->next->next;
            if(slow == fast)
            {
                sign = true;
                break;
            }
        }

        if(!sign) return NULL;

        //此时已经有
        slow = head;
        while(slow != fast)
        {
            slow = slow->next;
            fast = fast->next;
        }

        return slow;

        
    }
};

总结:C++快慢指针

十、栈的最小值
力扣刷题记录2-29-2020-3-1_第10张图片

class MinStack {

    //两个辅助栈
private:
    stack<int>mainStack;
    stack<int>helpStack;

public:

    /** initialize your data structure here. */
    MinStack() {

    }
    
    void push(int x) {
        mainStack.push(x);
        if(helpStack.empty()) helpStack.push(x);
        else
        {
            //当辅助栈第一个元素大于X则X进栈
            if(helpStack.top() > x) helpStack.push(x);
            else
            {
                int tmp = helpStack.top();
                helpStack.push(tmp);
            }
        }

    }
    
    void pop() {
        
        mainStack.pop();
        helpStack.pop();
    }
    
    int top() {
        return mainStack.top();
    }
    
    int getMin() {

        return helpStack.top();

    }
};

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack* obj = new MinStack();
 * obj->push(x);
 * obj->pop();
 * int param_3 = obj->top();
 * int param_4 = obj->getMin();
 */

总结:C++使用两个栈来实现

你可能感兴趣的:(学习)