剑指offer--堆、栈,队列、链表题目总结

来源:互联网 发布:计算机算法有几个 编辑:程序博客网 时间:2024/05/17 06:34

剑指offer 

1.链表,添加链表

    

struct ListNode{    int val;    ListNode* pNext;}void AddToTail(ListNode**pHead, int value){   if()}
删除链表

void RemoveNode(ListNode**pHead,int value){   if(pHead==NULL||*pHead==NULL)     return;   ListNode* pDelete=NULL;   if(*pHead->val==value)      {            pDelete=*pHead;            *pHead=(*phead)->pNext;        }      else{          ListNode* pNode=*pHead;         while(pNode->pNext!=NUll&&PNode->pNext->pval==value)          {               pDelete=pNode->pNext;               pNode->pNext=pNode->pNext->pNext;             }         }         if(pDelete!=NULL)        {            delete pDelete;            pDelete=NULL;}

2. 从头到尾打印链表

    ***  struct ListNode {*        int val;*        struct ListNode *next;*        ListNode(int x) :*              val(x), next(NULL) {*        }*  };*///输入一个链表,从尾到头打印链表每个节点的值。class Solution {public:    vector<int> printListFromTailToHead(ListNode* head) {        stack<ListNode*> S;        ListNode* cur=head;        while(cur)            {            S.push(cur);            cur=cur->next;        }        vector<int>ans;        while(!S.empty())            {            cur=S.top();            S.pop();            ans.pushback(cur->val);                    }        return ans;      }};

3.在o(1)的时间内删除链表

/*struct ListNode {    int val;    struct ListNode *next;    ListNode(int x) :        val(x), next(NULL) {    }};*//*在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。   例如,链表1->2->3->3->4->4->5 处理后为 1->2->5  因为相同的结点全部都要删除,设置三个指针,一个指向当前结点,一个指向前一结点,一个指向下一结点,一旦遇到当前结点等于下一结点的情况,  那么就一直移动,直到遇到下一个结点不同的状况,再将前一个结点指向此时结点的位置。*/class Solution {public:    ListNode* deleteDuplication(ListNode* pHead)    {if(!pHead)            return;    ListNode* pPreNode=NULL;        ListNode* pNode=pHead;        while(pNode!=NULL)            {            ListNode* pNext=pNode->next;            bool needDelete=false;            if(pNext!=NULL&&pNode->val==pNext->val)                needDelete=true;                if(!needDelete)                  {                      pPreNode = pNode;                      pNode = pNode->next;                  }                  else                  {                      int value = pNode->val;                      ListNode *pToBeDel = pNode;                      while(pToBeDel!= NULL && pToBeDel->val == value)                      {                          pNextNode = pToBeDel->next;                          delete pToBeDel;                          pToBeDel = NULL;                          pToBeDel = pNextNode;                      }                      if(pPreNode==NULL)                          pHead = pNextNode;                      else                          pPreNode->next = pNextNode;                      pNode = pNextNode;                  }              }              return pHead;                          }};

4.链表的倒数第k个节点

一个指针先往前走k-1步,然后另外一个指针才开始走,当第一个指针走到尾部了,那么第二个指针正好指向了倒数第k个结点

/*struct ListNode {int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {}};*/class Solution {public:    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {            if(pListHead==nullptr || k==0)                return nullptr;              ListNode *first = pListHead;              for(int i = 1;i<k;i++)              {                  first = first->next;                  if(first==nullptr)                  return nullptr;              }              ListNode *second = pListHead;              while(first->next)              {                  first = first->next;                  second = second->next;              }              return second;      }};


5.反转链表

  输入一个链表,反转链表后,输出链表的所有元素。
保存新的前一结点,当前结点和下一结点三个指针,只要下一结点为空,那么我们就到了原本结点的尾部,这时正是新链表的头部

/*struct ListNode {int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {}};*/class Solution {public:    ListNode* ReverseList(ListNode* pHead) { if(pHead==nullptr)                  return nullptr;              ListNode *pNewlist = nullptr;              ListNode *pCur = pHead;              ListNode *pPre = nullptr;              while(pCur!=nullptr)              {                  ListNode *pNext = pCur->next;                  if(pNext == nullptr)                      pNewlist = pCur;                  pCur->next = pPre;                  pPre = pCur;                  pCur = pNext;              }              return pNewlist;      }};

6.合并两个排序的链表

/*struct ListNode {int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {}};*/class Solution {public:    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)    {           if(pHead1==nullptr)                  return pHead1;              if(pHead2==nullptr)                  return pHead2;              ListNode *ptr1 = pHead1;              ListNode *ptr2 = pHead2;              ListNode *newlist = new ListNode(0);              ListNode *cur = newlist;              while(ptr1&&ptr2)              {                  if(ptr1->val <= ptr2->val)                  {                      cur->next = ptr1;                      ptr1 = ptr1->next;                      cur = cur->next;                  }                  else                  {                      cur->next = ptr2;                      ptr2 = ptr2->next;                      cur = cur->next;                  }                  cur->next = nullptr;              }              if(ptr1)                  cur->next = ptr1;              if(ptr2)                  cur->next = ptr2;              return newlist->next;      }};

7.两个链表的第一个公共节点

/*struct ListNode {int val;struct ListNode *next;ListNode(int x) :val(x), next(NULL) {}};*/class Solution {public:    unsigned int GetLength(ListNode* Node)        {        unsigned int length=0;        ListNode* pNode=Node;        while(pNode!=NULL)            {            ++length;            pNode=pNode->next;        }        return length;    }    ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {        unsigned int length1=GetLength(pHead1);        unsigned int length2=GetLength(pHead2);        int dislength=length1-length2;        ListNode* pListNodeLong=pHead1;        ListNode* pListNodeShort=pHead2;        pListNodeLong=(length2>=length1)?pHead2:pHead1;        pListNodeShort=(length2<length1)?pHead2:pHead1;        for(int i=0;i<dislength;++i)            pHead2=pHead2->next;        while(pListNodeLong!=NULL)&&(pLietNodeShort!=NULL)&&(pListNodeLong!=pListNodeShort)            {            pListNodeLong=pListNodeLong->next;            pListNodeShort=pListNodeShort->next;        }        ListNode* pFirst=pListNodeLong;        return pFirst;    }};


8.二叉搜索树与双向链表


9.复杂链表的复制

题目描述

输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针指向任意一个节点),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)


11.两个栈实现一个队列

template <typename T>class CQueue{public:      CQueue(void);    ~CQueue(void);    void appendTail(const T& node);    T deleteHead();private:    stack<T> stack1;    stack<T> stack2;};template<class T>void CQueue<T>::appendTail(const T& node)//在队列尾部添加数据{    stack1.push(node);}template<class T>T CQueue<T>::deleteHead(){    T tmp = 0;    if (stack2.empty()) //若栈2为空    {        while (!stack1.empty())        {            tmp = stack1.top();            stack2.push(tmp);            stack1.pop();        }    }    tmp = stack2.top();    stack2.pop();    return tmp;}

12.包含min函数的栈



13.栈的压入和弹出序列

/*输入两个整数序列,第一个序列表示栈的压入顺序, 请判断第二个序列是否为该栈的弹出顺序。假设压入 栈的所有数字均不相等。例如序列1,2,3,4,5是某栈 的压入顺序,序列4,5,3,2,1是该压栈序列对应的 一个弹出序列,但4,3,5,1,2就不可能是该压栈序列 的弹出序列。算法描述:首先判断两个序列的元素数目是否相等, 不相等,则肯定不是; 相等,进入下一步: 遍历Pop,每遍历一个数,先将Push数组里的压入栈,以i为push数组游标, 直到栈顶值与当前Pop值相等, ,然后弹出栈顶值,如果 直到i大于push数组的大小还没碰到栈顶值与pop数组相等 的值,则返回false*/class Solution {public:    bool IsPopOrder(vector<int> pushV,vector<int> popV) {        if (pushV.size() != popV.size())            return false;        stack<int> s;        int i = 0;        for (int popData : popV)        {            while (s.empty() || s.top() != popData) {                if (i == pushV.size())                    return false;                s.push(pushV[i++]);            }            s.pop();        }        return true;    }};


14. 题目描述

一个链表中包含环,请找出该链表的环的入口结点。

/*struct ListNode {    int val;    struct ListNode *next;    ListNode(int x) :        val(x), next(NULL) {    }};*/class Solution {public:    ListNode* EntryNodeOfLoop(ListNode* pHead)    {            ListNode *pSlow = pHead;              ListNode *pFast = pHead;              do              {                  if(!pSlow||!pFast)                      return nullptr;                  pSlow = pSlow->next;                  pFast = pFast->next;                  if(pFast)                      pFast = pFast->next;                  else                      return nullptr;              }              while(pSlow!=pFast);                pSlow = pHead;              while(pSlow!=pFast)              {                  pSlow = pSlow->next;                  pFast = pFast->next;              }              return pSlow;              }};



2. 剑指offer 寻找链表中的倒数第k个节点,和编程之美中判断两个链表是否相交类似,都是从链表尾部开始的。



编程之美的两道题目 

1.从无头单链表中删除节点

   由于单链表没有头指针,,不能简单的删除,会使得链表被分割

  void DeleteRandomNode(Node* pCurrent)

   {

       Assert(pCurrent!=NULL)

*** struct ListNode {* int val;* struct ListNode *next;* ListNode(int x) :* val(x), next(NULL) {* }* };*///输入一个链表,从尾到头打印链表每个节点的值。class Solution {public: vector<int> printListFromTailToHead(ListNode* head) { stack<ListNode*> S; ListNode* cur=head; while(cur) { S.push(cur); cur=cur->next; } vector<int>ans; while(!S.empty()) { cur=S.top(); S.pop(); ans.pushback(cur->val); } return ans; }};

0 0