算法基础__第3课(数组实现队列和栈、实现能够获取最小值的栈、队实现栈、栈实现队、转圈打印矩阵、螺旋矩阵、链表反转(I、II)、之字形打印矩阵、有序矩阵找值、打印链表公共部分、带环链表问题)

用数组结构实现大小固定的队列和栈

//
//  arrtostackorqueue.cpp
//  basic3
//
//  Created by 吴珝君 on 2019/6/13.
//  Copyright © 2019年 闲着也是贤者. All rights reserved.
//

#include <iostream>
#include <iostream>
#include <stack>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <ctime>
using namespace std;
/************************************************************************/
/* 用数组实现固定大小的栈*/
/*******************************rr*****************************************/
/************************************************************************/
/* 设计:栈顶指针首先指向的是0位置,每次进栈的时候先存元素,然后栈顶元素++ 同样的
 出栈的时候正好相反*/
/************************************************************************/
class ArrayStack
{
public:
    ArrayStack(int init){
        arr = new int[init];//初始化栈
        tops =  0;//指向栈顶位置
        size = init;//存储栈的总的空间大小  
    }
    void	pop(){
        if (tops != 0){tops--;}
        else{ cout <<"栈为空"<<endl;}
    }
    void push(int s){
        if (tops == size ) {
            cout << "栈满" <<endl;
        }
        else{arr[tops++] = s;}
    }
    int top(){
        return arr[tops - 1];
    }
private:
    int size;	//栈的大小
    int tops;	//指定栈顶位置
    int *arr;	//存放栈元素的数组
    
};

/************************************************************************/
/* 用数组设计一个固定大小列                                                                     */
/************************************************************************/
class ArrayQueue
{
public:
    ArrayQueue(int init){
        arr = new int[init];
        fill(arr, arr+ init, 0);
        capacity = init;
    }
    //首先是入栈
    bool push(int q)
    {
        if (len < capacity){
            arr[end] = q;// 0 - capacity-1
            end =  (end +1) %capacity;//每次进出队列之后再进行处理
            len++;
        }
        else
            return  false;
        return true;
        
    }
    void  pop()
    {
        if (size()==0)
            return ;
        else{
            len--;
            start = (start + 1)%capacity;}
        
    }
    int size(){
        return len;
    }
    
    int top() {
        if (size() ==0){return INT_MIN;}
        else{return arr[start];}
    }
private:
    int len = 0;//队的实际长度
    int start = 0;//队头
    int end = 0;//队尾
    int *arr = NULL;//数组指针
    int capacity =0;//记录队列的最大值
};
实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返
回栈中最小元素的操作。
【要求】 1.pop、push、getMin操作的时间复杂度都是O(1)。 2.设计的栈类型可以使用现成的栈结构。
class MinStack {
public:
    std::stack<int> main;
    std::stack<int> help;
    MinStack() {
        // do intialization if necessary
    }

    /*
     * @param number: An integer
     * @return: nothing
     */
    void push(int number) {
        // write your code here
        if(main.empty()){
            main.push(number);
            help.push(number);
        }
        else{
            main.push(number);
            int top = help.top();
            if(top <  number){
                help.push(top);
            }
            else{
                help.push(number);
            }
        }
    }

    /*
     * @return: An integer
     */
    int pop() {
        // write your code here
        if(main.empty())
            return INT_MAX;
        else{
            int t = main.top();
            main.pop();
            help.pop();
            return t;
        }
    }

    /*
     * @return: An integer
     */
    int min() {
        // write your code here
        if(main.empty()) return INT_MAX;
        else{return help.top();}
    }
};
如何仅用队列结构实现栈结构?
如何仅用栈结构实现队列结构?
class MyQueue {
public:
    std::stack<int> main;
    std::stack<int> help;
    MyQueue() {
        // do intialization if necessary
    }

    /*
     * @param element: An integer
     * @return: nothing
     */
    void push(int element) {
        // write your code here
        main.push(element);
    }

    /*
     * @return: An integer
     */
    int pop() {
        // write your code here
      if(help.empty())
      {
          while(!main.empty())
          {
              help.push(main.top());
              main.pop();
          }
      }
      int  t = help.top();
      help.pop();
      return  t;
    }

    /*
     * @return: An integer
     */
    int top() {
        // write your code here
         if(help.empty())
      {
          while(!main.empty())
          {
              help.push(main.top());
              main.pop();
          }
      }
        return help.top();
    }
};
class MyStack {
public:
    queue<int> main;
    queue<int> help;
    /** Initialize your data structure here. */
    MyStack() {
        
    }
    
    /** Push element x onto stack. */
    void push(int x) {
        main.push(x);
    }
    
    /** Removes the element on top of the stack and returns that element. */
    int pop() {
      //
        int len = main.size();
        int res = 0;
        for(int i = 0; i < len -1 ; i++){
           res = main.front();
            main.pop();
            help.push(res);
        }
        res = main.front();
        main.pop();
        queue<int> t = main;
        main = help;
        help = t;//这里需要注意的问题是我们每次操作都需要将辅助栈清空,否则会出错
        return res;
    }
    
    /** Get the top element. */
    int top() {
        int len = main.size();
        int res = 0;
        for(int i = 0; i < len ; i++){
           res = main.front();
            main.pop();
            help.push(res);
        }
        queue<int> t = main;
        main = help;
        help = t;//清空辅助栈
        return res;
    }
    
    /** Returns whether the stack is empty. */
    bool empty() {
        return main.empty();
    }
};

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack* obj = new MyStack();
 * obj->push(x);
 * int param_2 = obj->pop();
 * int param_3 = obj->top();
 * bool param_4 = obj->empty();
 */
给定一个包含 m x n 个要素的矩阵,(m 行, n 列),按照螺旋顺序,返回该矩阵中的所有要素。

样例
样例 1:

输入:[[ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ]]
输出: [1,2,3,6,9,8,7,4,5]
样例 2

输入:[[ 6,4,1 ], [ 7,8,9 ]]
输出: [6,4,1,9,8,7]
class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) 
    {
        vector<int> res;
        int i = 0;//开始行
        int j = 0;//开始列
        if(matrix.size() == 0)
            return res;//边界条件
        int down = matrix.size()-1;//终止行
        int right = matrix[0].size()-1;//终止列
        //不用递归 用while循环实现
        while(i <=down && j <=right)
        {
            if(i ==down)
            {
                for(int s =j; s <=right; s++)
                 res.push_back(matrix[i][s]);
                break;
            }
            if(j == right)
            {
                for(int s = i; s<=down;s++)
                {
                    res.push_back(matrix[s][j]);
                }
                 break;//注意这里要退出循环
            }
        for(int k = j; k < right;k++)
         res.push_back(matrix[i][k]);
       for(int p =i; p <down; p++)
          res.push_back(matrix[p][right]);
        for(int m =right; m >j; m-- )
          res.push_back(matrix[down][m]);
        for(int n =down; n >i; n--)
            res.push_back(matrix[n][j]);
        i++;
        j++;
        down--;
        right--;
        }
        
      return res;  
    }
};
769. 螺旋矩阵
给出整数 n, 返回一个大小为 n * n 的螺旋矩阵

样例
样例 1:

输入 : n = 3
输出 :
[
[1,2,3]
[8,9,4]
[7,6,5]
]
样例 2:

输入 : n = 5
输出 : 
[[1,2,3,4,5]
 [16,17,18,19,6]
 [15,24,25,20,7]
 [14,23,22,21,8]
 [13,12,11,10,9]]
class Solution {
public:
    /**
     * @param n: a Integer
     * @return: a spiral array
     */
    vector<vector<int>> spiralArray(int n) {
        // write your code here
        int i = 0;//开始行
        int j = 0;//开始列
        int index = 1;
        int down = n-1;//终止行
        int right = n -1;
        //不用递归 用while循环实现
        vector<vector<int>> res( n,vector<int>(n) );
        while(i <=down && j <=right)
        {
            if(i ==down)
            {
                for(int s =j; s <=right; s++)
                 res[i][s] = index++;
                break;
            }
            if(j == right)
            {
                for(int s = i; s<=down;s++)
                {
                    res[s][j] = index++;
                  //  res.push_back(matrix[s][j]);
                }
                 break;//注意这里要退出循环
            }
        for(int k = j; k < right;k++)
            res[i][k] = index++;
       for(int p =i; p <down; p++)
          res[p][right] =index++;
        for(int m =right; m >j; m-- )
          res[down][m] = index++;
        for(int n =down; n >i; n--)
            res[n][j] = index++;
        i++;
        j++;
        down--;
        right--;
        }
        
      return res;  
    }
};
矩阵旋转90度
class Solution {
public:
    /**
     * @param matrix: a lists of integers
     * @return: nothing
     */
    void rotate(vector<vector<int>> &matrix) {
        // write your code here
        if(matrix.size() ==0)
        return;
        int tR = 0,tC =0, dR = matrix.size() -1, dC = matrix[0].size() -1;
        while(tR < dR)
        {
        move(matrix, tR++,tC++,dR--,dC--);
        }
    }
    void move(vector<vector<int>> &matrix, int topRow, int topCol, int downRow, int downCol)
    {
        //要移动元素的组数
        int times =  downCol - topCol;
        for (int i = 0; i < times; i++) 
        {
            /* code */
            int temp = matrix[topRow][topCol+i];
            matrix[topRow][topCol + i] = matrix[downRow - i][topCol];
            matrix[downRow - i][topCol] = matrix[downRow][downCol - i];
            matrix[downRow][downCol - i] = matrix[topRow+i][downCol];
            matrix[topRow + i][downCol] = temp;
        }
        
    }
};
反转单向链表

 

/**
 * Definition of singly-linked-list:
 *
 * class ListNode {
 * public:
 *     int val;
 *     ListNode *next;
 *     ListNode(int val) {
 *        this->val = val;
 *        this->next = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param head: n
     * @return: The new head of reversed linked list.
     */
    ListNode * reverse(ListNode * head) {
        // write your code here
        ListNode *pre = NULL;
        ListNode *cur = head;
        ListNode* next =NULL ;
        while(cur)
        {
         //找到当前的下一个位置
          next = cur->next;
          cur->next = pre;
          pre = cur;
          cur = next;
        }
        return pre;

    }
};
36. 翻转链表 II
中文
English
翻转链表中第m个节点到第n个节点的部分

样例
例1:

输入: 1->2->3->4->5->NULL, m = 2 and n = 4, 
输出: 1->4->3->2->5->NULL.
例2:

输入: 1->2->3->4->NULL, m = 2 and n = 3, 
输出: 1->3->2->4->NULL.
挑战
Reverse it in-place and in one-pass

注意事项
m,n满足1 ≤ m ≤ n ≤ 链表长度
/**
 * Definition of singly-linked-list:
 * class ListNode {
 * public:
 *     int val;
 *     ListNode *next;
 *     ListNode(int val) {
 *        this->val = val;
 *        this->next = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param head: ListNode head is the head of the linked list 
     * @param m: An integer
     * @param n: An integer
     * @return: The head of the reversed ListNode
     */
    ListNode * reverseBetween(ListNode * head, int m, int n) {
        // write your code here
        ListNode *falseHead = new ListNode(0);//这里需要的就是加个头就就不用处理
    // 断开位置是头的情况
            falseHead->next = head;
            ListNode *curr  = falseHead;//处理断开位置是头节点的时候的处理。
            for (int i = 1; i < m; i++) {
                /* code */
                curr = curr->next;
            }
            ListNode *preHead = curr;//断开位置m的前一个节点
        ListNode* preEnd = preHead->next;
        int times = n - m;
        ListNode *pre = NULL;
        ListNode *cur = preEnd;
        ListNode* next =NULL ;
        while(times >=0)
        {
         //找到当前的下一个位置
          next = cur->next;
          cur->next = pre;
          pre = cur;
          cur = next;
          times--;
        }
        //最后的位置是next
         preHead->next = pre;
         preEnd->next = next;//next为n的后一个节点
        
     return falseHead->next;    
    }
   
};
之字形打印矩阵

1、思路,第一种,只维持一个从左到右和从上到下的变量。我们标记第一行为偶数行,那么当我们遇到
基数行的时候就从上往下存入数组,当我们遇到基数行的时候,我们先把结果存储栈中,然后,再通过出栈
将所有元素保存到数组中。

2、维持两组变量分别记录从左到右,从上到下的坐标变化,以及从上到下和从左到右的变化。并维持一个标志
位,来标识打印顺序。有了这样两组变量,我们可以很容易找到要处理的坐标位置。
难点是对坐标变量的维持。特别是变量的先后处理顺序,对从左到右从上到下的变量处理来说,应该先处理
从上到下的变量,因为如果先处理从左到右的变量会导致,最后一次恰好使得条件满足,使得从左到右的变量值
要加上1,同时,从上到下的变量也加上1 这样导致了错误。
//way1
class Solution {
public:
    /**
     * @param matrix: An array of integers
     * @return: An array of integers
     */
    vector<int> printZMatrix(vector<vector<int>> &matrix) {
        // write your code here
       int i = 0;
       vector<int> res;
        for (int j = 0; j < matrix[0].size(); j++) {
            /* code */
            int i = 0;
            int k = j;
            
            if(j%2 == 1)
            {
            while( i <matrix.size()&&k >= 0)
            {
            res.push_back(matrix[i++][k--]);
            }
            }
            else
            {
                std::stack<int> s;
             while( i <matrix.size()&&k >= 0)
            {
            
            s.push(matrix[i++][k--]);
            }
            while(!s.empty())
            {
               res.push_back(s.top()); 
               s.pop();
            }
            }
        }
        int index = matrix[0].size();
        for (int i = 1; i < matrix.size() ; i++) {
            /* code */
            int j = matrix[0].size()-1;//lie
            int k = i;
            if( index%2 == 1)
            {
            while(k < matrix.size() &&j >=0)
            {
                res.push_back(matrix[k++][j--]);
            }
            }
            else
            {
                 std::stack<int> s;
             while( k <matrix.size()&&j >= 0)
            {
            s.push(matrix[k++][j--]);
            }
            while(!s.empty())
            {
               res.push_back(s.top()); 
               s.pop();
            }
            }
            index++;
        }
        return res;
    }
};
way2
class Solution {
public:
    /**
     * @param matrix: An array of integers
     * @return: An array of integers
     */
      vector<int> res;
    vector<int> printZMatrix(vector<vector<int>> &matrix) {
        // write your code here
       int downCol = 0;
       int downRow = 0;
       int upRow = 0;
       int upCol = 0;
       int endCol = matrix[0].size();
       int endRow = matrix.size();//错误位置1 
       bool fromUp = false;
       while(upRow < endRow)
       {
          prints(matrix, upRow,upCol,downRow,downCol,fromUp);
           upRow  =  upCol == endCol - 1 ? upRow +1 : upRow;
           upCol  = upCol == endCol- 1 ? upCol : upCol + 1;
           downCol = downRow == endRow - 1? downCol + 1 : downCol;
           downRow = downRow == endRow -1? downRow : downRow + 1;//错误位置2
           fromUp = !fromUp;
       }
        return res;
    }
  void   prints(vector<vector<int>> matrix, int upRow, int upCol, int downRow, int downCol, bool fromUp)
    {
        if(fromUp)
        {
            while(upRow != downRow +1)
            {
                res.push_back(matrix[upRow++][upCol--]);
            }
        }
        else
        {
            while(downRow != upRow -1)
            {
                res.push_back(matrix[downRow--][downCol++]);
            }
        }
    }
};
【题目】 给定一个有N*M的整型矩阵matrix和一个整数K, matrix的每一行和每一 列都是排好序的。实现一个
函数,判断K 是否在matrix中。 例如: 0 1 2 5 2 3 4 7 4
4 4 8 5 7 7 9 如果K为7,返回true;如果K为6,返 回false。
【要求】 时间复杂度为O(N+M),额外空间复杂度为O(1)。
class Solution
{
public:
    bool  findK(vector<vector<int>> matrix, int k) {
        int endRow = matrix.size();
        int col = matrix[0].size()-1;
        int row = 0;
        while (col>=0 && row < endRow ) {
            if (matrix[row][col] == k){
                return true;
            }
            else if(matrix[row][col] > k){
                row++;
            }
            else {col--; }
        }
        return false;
    }  
};
打印两个有序链表的公共部分
【题目】 给定两个有序链表的头指针head1和head2,打印两个 链表的公共部分。
/**
 * Definition of singly-linked-list:
 * class ListNode {
 * public:
 *     int val;
 *     ListNode *next;
 *     ListNode(int val) {
 *        this->val = val;
 *        this->next = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param headA: the first list
     * @param headB: the second list
     * @return: a ListNode
     */
    ListNode * getIntersectionNode(ListNode * headA, ListNode * headB) {
        // write your code here
        int lenA = 0;
        int lenB = 0;
        ListNode * head = headA;
        ListNode *sA = NULL;
        ListNode *sB = NULL;
        while(head){
            lenA++;
            head = head->next;
        }
        head = headB;
        while(head){
            lenB++;
            head = head->next;
        }
     int sub = abs(lenA - lenB);
     if( lenA > lenB)
     {
         head = headA;
         while(sub >0){
            head = head->next;
            sub--;
         }
         sA = head;
         sB = headB;
     }
     else
     { head = headB;
         while(sub >0){
            head = head->next;
            sub--;
         }
         sB = head;
         sA = headA;
     }
     while(sA)
     {
         if(sA == sB){return sA;}
         else
         {
             sA = sA->next;
             sB = sB->next;
         }
         
     }
     return sA;
    }
};
判断一个链表是否为回文结构
【题目】 给定一个链表的头节点head,请判断该链表是否为回 文结构。 例如: 1->2->1,返回true。 1->2-
>2->1,返回true。 15->6->15,返回true。 1->2->3,返回false。
进阶: 如果链表长度为N,时间复杂度达到O(N),额外空间复杂 度达到O(1)。
class Solution {
public:
    /**
     * @param head: A ListNode.
     * @return: A boolean.
     */
    bool isPalindrome(ListNode * head) {
        int len =0;
        ListNode *startPre = NULL;
        ListNode *falseNode = new ListNode(0);
        falseNode->next = head;
        ListNode *h = head;
        while(h){
            len++;
            h = h->next;
        }
        int halflen = len/2;
        h = falseNode;
        while(halflen > 0){
            h = h->next;//找到
            halflen--;
        }
        startPre = h;
        h = h->next;
        startPre->next = NULL;
        ListNode *end = reverse(h);
        h = head;
        ListNode *ends = end;
        while(h){
            if(h->val == ends->val){
                    h = h->next;
                    ends = ends->next;
                    continue;
            }
            else
                return false;
        }
        ListNode *start = reverse(end);
        startPre->next = start;
        return true;
    }
    ListNode * reverse(ListNode * root)
    {
        ListNode * pre = NULL;
        ListNode * next = NULL;
        ListNode *cur = root;
        while(cur){
            next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }
};
class Solution {
public:
    /**
     * @param head: A ListNode.
     * @return: A boolean.
     */
    bool isPalindrome(ListNode * head) {
        int len =0;
        if(head == NULL || head->next == NULL)
        return true;
        ListNode *h = head;
        ListNode * oneStep = head;
        ListNode *twoStep = head;
        while(twoStep->next&& twoStep->next->next) {
            oneStep = oneStep->next;
            twoStep = twoStep->next->next;
        }//找到中间位置
        twoStep = oneStep->next;
        oneStep->next =NULL;
        ListNode *end = reverse(twoStep);
        h = head;
        ListNode *ends = end;
        while(ends){
            if(h->val == ends->val){
                    h = h->next;
                    ends = ends->next;
                    continue;
            }
            else
                return false;
        }
        ListNode *start = reverse(end);
        oneStep->next = start;
        return true;
    }
    ListNode * reverse(ListNode * root)
    {
        ListNode * pre = NULL;
        ListNode * next = NULL;
        ListNode *cur = root;
        while(cur){
            next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }
};
给出一个链表,每个节点包含一个额外增加的随机指针可以指向链表中的任何节点或空的节点。

返回一个深拷贝的链表。 

挑战
可否使用O(1)的空间

class Solution {
public:
    unordered_map<RandomListNode *, RandomListNode*> help;
    /**
     * @param head: The head of linked list with a random pointer.
     * @return: A new head of a deep copy of the list.
     */
    RandomListNode *copyRandomList(RandomListNode *head) {
        // write your code here
        RandomListNode *cur = head;
        while(cur)
        {
           help.insert(pair<RandomListNode*, RandomListNode*>(cur, new RandomListNode(cur->label)));
            cur = cur->next;
        }
        cur = head;
        while(cur){
            RandomListNode * temp = help.find(cur)->second;
            if(cur->next)//注意判空处理
            temp->next = help.find(cur->next)->second;
             if(cur->random)//注意判空处理
            temp->random = help.find(cur->random)->second;//
            cur = cur->next;
        }
        return  help.find(head)->second;
    }
};
两个单链表相交的一系列问题
【题目】 在本题中,单链表可能有环,也可能无环。给定两个 单链表的头节点 head1和head2,这两个链表可能
相交,也可能 不相交。请实现一个函数, 如果两个链表相交,请返回相交的 第一个节点;如果不相交,返回
null 即可。 要求:如果链表1 的长度为N,链表2的长度为M,时间复杂度请达到 O(N+M),额外 空间复杂度请达
到O(1)。
(1)判断链表是否有环
class Solution {
public:
    unordered_map<ListNode*,ListNode*> help;
    /**
     * @param head: The first node of linked list.
     * @return: True if it has a cycle, or false
     */
    bool hasCycle(ListNode * head) {
        // write your code here
      if(head == NULL||head->next == NULL||head->next->next == NULL)
         return false;
        ListNode *oneStep = head->next;
        ListNode *twoStep = head->next->next;
        while(twoStep->next && twoStep->next->next) {
            if(oneStep == twoStep) {
                return true;//注意头两个节点一定相同
            }
            oneStep = oneStep->next;
            twoStep = twoStep->next->next;
        }
        return false;
    }
};
class Solution {
public:
    unordered_map<ListNode*,ListNode*> help;
    /**
     * @param head: The first node of linked list.
     * @return: True if it has a cycle, or false
     */
    bool hasCycle(ListNode * head) {
        // write your code here
    while(l1){
            if(help.count(l1) == 0)
            help.insert(pair<ListNode*, ListNode *>(l1,l1));
            else {return true;}
            l1 = l1->next;
        }
        return false;
    }
};
//
//  main.cpp
//  basic3
//
//  Created by 吴珝君 on 2019/6/13.
//  Copyright © 2019年 闲着也是贤者. All rights reserved.
//

#include <iostream>
#include <iostream>
#include <stack>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <queue>
using namespace std;
//
//  test.h
//  test
//
//  Created by 吴珝君 on 2018/12/27.
//  Copyright  ©   2018年 闲着也是贤者. All rights reserved.
//
/************************************************************************/

class ListNode {
public:
    int val;
    ListNode *next;
    ListNode(int val) {
        this->val = val;
        this->next = NULL;
    }
};


class Solution {
public:
    /**
     * @param head: The first node of linked list.
     * @return: True if it has a cycle, or false
     */
    ListNode* findInsection(ListNode *head1, ListNode *head2)
    {
        if(head1 == NULL || head2 == NULL){
            return NULL;
        }
        ListNode* hasCycle1 = hasCycle(head1);
        ListNode* hasCycle2 = hasCycle(head2);
        if((hasCycle1 && !hasCycle2) || (!hasCycle1 && hasCycle2))
            return NULL;
        if(!hasCycle1 && !hasCycle2){
            return    getIntersectionNodeNoCircle( head1, head2);
        }
        else{
            return getIntersectionNodeWithCircle(hasCycle1, hasCycle2);
        }
    }
    ListNode * getIntersectionNodeWithCircle(ListNode * headA, ListNode * headB) {
        // write your code here
        cout <<"withCircle"<<endl;
        ListNode *l1 = headA->next;
        ListNode *l2 = headB->next->next;
        while(l1 != headA)
        {
            if(l1 == l2){
                return headA;
            }
            else{
                l1 = l1->next;
                l2 = l2->next->next;
            }
        }
        return NULL;
    }
    ListNode * getIntersectionNodeNoCircle(ListNode * headA, ListNode * headB) {
        // write your code here
        cout <<"withNoCircle"<<endl;
        int lenA = 0,lenB = 0;
        ListNode * head = headA, *sA = NULL,*sB = NULL;
        while(head){
            lenA++;head = head->next;
        }
        head = headB;
        while(head){
            lenB++; head = head->next;
        }
        int sub = abs(lenA - lenB);
        if( lenA > lenB){
            head = headA;
            while(sub >0){
                head = head->next; sub--;
            }
            sA = head;sB = headB;
        }
        else
        {   head = headB;
            while(sub >0){
                head = head->next; sub--;
            }
            sB = head;
            sA = headA;
        }
        while(sA) {
            if(sA == sB){return sA;}
            else{
                sA = sA->next; sB = sB->next;
            }
        }
        return sA;
    }
    ListNode* hasCycle(ListNode * head) {
        // write your code here
        if(head == NULL||head->next == NULL||head->next->next == NULL)
            return NULL;
        ListNode *oneStep = head->next;
        ListNode *twoStep = head->next->next;
        while(twoStep->next && twoStep->next->next) {
            if(oneStep == twoStep) {
                return oneStep;//注意头两个节点一定相同
            }
            oneStep = oneStep->next;
            twoStep = twoStep->next->next;
        }
        return NULL;
    }
};



int main(int argc, const char * argv[]) {
    Solution s;
    ListNode* head1 = new ListNode(1);
    head1->next = new ListNode(2);
    head1->next->next = new ListNode(3);
    head1->next->next->next = new ListNode(4);
    head1->next->next->next->next = new ListNode(5);
    head1->next->next->next->next->next = new ListNode(6);
    head1->next->next->next->next->next->next = new ListNode(7);
    
    // 0->9->8->6->7->null
    ListNode* head2 = new ListNode(0);
    head2->next = new ListNode(9);
    head2->next->next = new ListNode(8);
    head2->next->next->next = head1->next->next->next->next->next; // 8->6
    cout << s.findInsection(head1, head2)->val<<endl;
    // 1->2->3->4->5->6->7->4...
    head1 = new ListNode(1);
    head1->next = new ListNode(2);
    head1->next->next = new ListNode(3);
    head1->next->next->next = new ListNode(4);
    head1->next->next->next->next = new ListNode(5);
    head1->next->next->next->next->next = new ListNode(6);
    head1->next->next->next->next->next->next = new ListNode(7);
    head1->next->next->next->next->next->next = head1->next->next->next;
    
    // 0->9->8->2...
    head2 = new ListNode(0);
    head2->next = new ListNode(9);
    head2->next->next = new ListNode(8);
    head2->next->next->next = head1->next; // 8->2
     cout << s.findInsection(head1, head2)->val<<endl;
    // 0->9->8->6->4->5->6..
    head2 = new ListNode(0);
    head2->next = new ListNode(9);
    head2->next->next = new ListNode(8);
    head2->next->next->next = head1->next->next->next->next->next; // 8->6
    cout << s.findInsection(head1, head2)->val<<endl;
    //cout <<"ok" <<endl;
}
96. 链表划分
给定一个单链表和数值x,划分链表使得所有小于x的节点排在大于等于x的节点之前。

你应该保留两部分内链表节点原有的相对顺序。



样例
样例 1:

输入: list = null, x = 0
输出: null	
样例解释: 空链表本身满足要求
样例 2:

输入: list = 1->4->3->2->5->2->null, x = 3
输出: 1->2->2->4->3->5->null	
样例解释: 要保持原有的相对顺序。
class Solution {
public:
    ListNode *partition(ListNode *head, int x) {
        ListNode *dummy = new ListNode(INT_MIN);
        dummy->next = head;//为了防止第一个就是不满足条件的节点的情况
        ListNode *pre = dummy, *cur = head;
        while (pre->next && pre->next->val < x) pre = pre->next;//Z找到第一个需要保存的旧的链表的前驱
        cur = pre;
        while (cur->next) {
            if (cur->next->val < x) {
                ListNode *tmp = cur->next;
                cur->next = tmp->next;
                tmp->next = pre->next;
                pre->next = tmp;
                pre = pre->next;
            } else {
                cur = cur->next;
            }
        }
        return dummy->next;
    }
};
class Solution {
public:
    ListNode *partition(ListNode *head, int x) {
        ListNode *sHead = NULL, *sTail = NULL, *bHead = NULL, *bTail =NULL;
        while(head){
            if(head->val < x){
              if(sHead == NULL){
                  sHead = head;
                  sTail = head;
              }
             else{
                 sTail->next = head;
                 sTail = sTail->next;
             }
            }
            else{
                if(bHead == NULL){
                    bHead = head;
                    bTail = head;
                }
                else{
                    bTail->next = head;
                    bTail = bTail->next;
                }
            }
            head = head->next;
        }
        if(sHead !=NULL){sTail->next =NULL;}
        if(bHead !=NULL){bTail->next =NULL; }
        if(sHead != NULL){
            sTail->next = bHead;
            return sHead;
        }
        else
        return bHead;
    }
};

class Solution {
public:
    /**
     * @param head: The first node of linked list
     * @param x: An integer
     * @return: A ListNode
     */
    ListNode * partition(ListNode * head, int x) {
        // write your code here
        //分成三个部分和两个部分本质是一样的
        ListNode *sHead = NULL, *sTail = NULL, *mHead =NULL,*mTail = NULL,*bTail= NULL,*bHead =NULL;
        //采用尾插法
        while (head) {
            if(head->val < x){
                if (sHead == NULL) {
                    sHead = head;
                    sTail = head;
                }
                else{
                    sTail->next = head;
                    sTail = sTail->next;
                }
            }
            else if(head->val ==x){
                if (mHead == NULL) {
                    mHead = head;
                    mTail = head;
                }
                else{
                    mTail->next = head;
                    mTail = mTail->next;
                }
            }
            else{
                if (bHead == NULL) {
                    bHead = head;
                    bTail = head;
                }
                else{
                    bTail->next = head;
                    bTail = bTail->next;
                }
            }
            head = head->next;
        }
        if(sHead!=NULL){sTail->next =NULL;}
        if(mHead!=NULL){mTail->next = NULL;};
        if(bHead !=NULL){bTail->next =NULL;};
        if (sHead != NULL) {
            sHead->next = mHead;
            mTail = mTail== NULL ? sTail :mTail;
        }
        if (mTail !=NULL) {
            mTail->next = bHead;
        }
        return sHead !=NULL ? sHead : (mHead !=NULL ? mHead :bHead);
        if ((sHead !=NULL)) {
            sHead->next = mHead;
            if (mHead !=NULL) {mHead->next = bHead;}
            else{sTail->next = bHead;}
        }
        else{
            if (mHead !=NULL) {
                sHead = mHead;
                mTail->next = bHead;
            }
            else{sHead = bHead;}
        }
        return sHead;
    }
};

本题唯一需要说明的问题在于将新的链表尾部节点的设置为空,否则系统将无法找到链表的结束节点,而导致错误。

复制含有随机指针节点的链表
【题目】 一种特殊的链表节点类描述如下:
public class Node { public int value; public Node next; public Node rand;
public Node(int data) { this.value = data; }
} Node类中的value是节点值,next指针和正常单链表中next指针的意义 一 样,都指向下一个节点,rand指针
是Node类中新增的指针,这个指 针可 能指向链表中的任意一个节点,也可能指向null。 给定一个由 Node节点
类型组成的无环单链表的头节点head,请实现一个 函数完成 这个链表中所有结构的复制,并返回复制的新链表
的头节点。 进阶: 不使用额外的数据结构,只用有限几个变量,且在时间复杂度为 O(N) 内完成原问题要实现的
函数。

class Solution {
public:
    unordered_map<RandomListNode *, RandomListNode*> help;
    /**
     * @param head: The head of linked list with a random pointer.
     * @return: A new head of a deep copy of the list.
     */
    RandomListNode *copyRandomList(RandomListNode *head) {
        // write your code here
        RandomListNode *cur = head;
        if(cur == NULL) return NULL;
        while(cur)
        {
           help.insert(pair<RandomListNode*, RandomListNode*>(cur, new RandomListNode(cur->label)));
            cur = cur->next;
        }
        cur = head;
        while(cur){
            RandomListNode * temp = help.find(cur)->second;
            if(cur->next)//注意判空处理
            temp->next = help.find(cur->next)->second;
             if(cur->random)//注意判空处理
            temp->random = help.find(cur->random)->second;//
            cur = cur->next;
        }
        return  help.find(head)->second;
    }
};

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值