Cracking the coding Interview: ListNode

来源:互联网 发布:mac双系统修复windows 编辑:程序博客网 时间:2024/06/11 04:58

  • Return kth to Last
  • Delete Middle Node
  • Partition
  • palindrome
  • Sum Lists
  • Remove Dups
  • Intersection
  • Loop Detection

Return kth to Last

法一:就是计算有多少个节点,然后减去k,接着遍历。

class Solution {public:    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {        int len = 0;        if(pListHead == NULL) return NULL;        ListNode* tmp = pListHead;        while(tmp != NULL) {            len++;            tmp = tmp->next;        }        tmp = pListHead;        int cnt = len - k;        if(cnt < 0) return NULL;        while(tmp != NULL && cnt-- != 0) tmp = tmp->next;         if(tmp == NULL) return NULL;        return tmp;        }};

法二:
使用递归计算最后k个节点。

比如一个list是a->b->c->d。那么递归会一直调用到d,如果k为2,d调用的时候下一个为NULL,所以返回。这个时候cnt为1,不相等,就返回nd = NULL。然后到了c这一级,cnt = 2,满足条件,就把c这个节点的指针返回。到了d这一级,cnt为3,就把上次返回的结果返回。

class Solution {public:    ListNode* kThLast(ListNode* p, unsigned int k, int &cnt) {        if(!p) return NULL;        ListNode* nd = kThLast(p->next, k, cnt);         cnt++;        if(k == cnt) return p;        return nd;    }    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {        int i = 0;        return kThLast(pListHead, k, i);    }};

这里可以把程序写得更加规整一点,使用一个类。

class Index {    public: unsigned int value = 0;  };class Solution {public:    ListNode* kThLast(ListNode* p, unsigned int k, Index* ind) {        if(!p) return NULL;        ListNode* nd = kThLast(p->next, k, ind);         ind->value++;        if(k == ind->value) return p;        return nd;    }    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {        Index* ind = new Index();        return kThLast(pListHead, k, ind);    }};

法三:快慢指针的使用
首先把一个指针指向第k个节点,然后另外一个节点从开头出发,第一个遍历的节点为遍历的结束的时候,第二个节点就正好到了最后的第k个元素。

class Solution {public:    ListNode* FindKthToTail(ListNode* p, unsigned int k) {        ListNode* p1 = p, *p2 = p;        for(unsigned int i = 0; i < k ; i++) {            if(p2) p2 = p2->next;            else return NULL;        }            while(p2) { p1 = p1->next; p2 = p2->next; }        return p1;    }};

Delete Middle Node

使用快慢指针进行计算就可以得到所想要的结果。一个指向下一个,另外一个指向下下一个。

class Remove {public:    bool removeNode(ListNode* p) {        // write code here        ListNode* p1 = p, *p2 = p;        while(p2) {            if(p2->next) p2 = p2->next->next;            else break;            p1 = p1->next;        }        return p1 != p2;    }};

Partition

把一个List分成两个,左边小于x,右边不小于x。可以使用两个list存储,再进行合并。

class Partition {public:    ListNode* partition(ListNode* pHead, int x) {        // write code here        ListNode* p1s = new ListNode(0), *p1e= NULL, *p2s = new ListNode(0), *p2e = NULL;        while(pHead) {            if(pHead->val < x) {                ListNode *tmp = new ListNode(pHead->val);                if(!p1e) { p1e = tmp; p1s->next = p1e; }                else { p1e->next = tmp; p1e = tmp; }            }            else {                ListNode *tmp = new ListNode(pHead->val);                if(!p2e) { p2e = tmp; p2s->next = p2e; }                else { p2e->next = tmp; p2e = tmp; }                            }            pHead = pHead->next;        }        if(p1e) p1e->next = p2s->next;        return p1e?p1s->next:p2s->next;    }};

palindrome

这道题目就是求一个字符串是否是回文串。可以先找到中点,同时把前半部分压到栈中,再把栈中元素和后半部分作比较。

class Palindrome {public:    bool isPalindrome(ListNode* pHead) {        // write code here        stack<int> stk;        ListNode* p1 = pHead, *p2 = pHead;        while(p1 && p1->next) {            stk.push(p2->val);            p1 = p1->next->next;            p2 = p2->next;        }        if(p1 && !p1->next && p2) p2 = p2->next;        p1 = pHead;        while(p1 && p2) {            int tp = stk.top();            if(tp == p2->val) stk.pop();            p1 = p1->next;            p2 = p2->next;        }        return stk.empty();    }};

Sum Lists

求两个List的和。

class Plus {public:    ListNode* plusAB(ListNode* a, ListNode* b) {        // write code here        ListNode* res = new ListNode(0);        ListNode* tmp = res;        int  cf = 0;        while(a || b || cf) {            int t1 = (a?a->val:0), t2 = (b?b->val:0);            int val = (t1 + t2 +cf)%10;            cf = (t1 + t2 +cf)/10;            ListNode* new_node = new ListNode(val);            tmp->next = new_node;            tmp = new_node;            if(a) a = a->next;            if(b) b = b->next;        }        return res->next;    }};

Remove Dups

这道题目使用哈希表,那么就是计算复杂度O(n)和空间复杂度O(n)。

如果使用暴力破解,那么就是空间复杂度O(1)和时间复杂度O(n^2)。

Intersection

计算两个链表的交点,可以先遍历到底,比较最后的节点。或者先遍历其中一个链表,使最后的指针指向开始的节点。那么另外一个指针在遍历的时候,如果相交,那么就会到另外一个链表的起点。同时还可以使用哈希表存储各个节点的地址,不过地址大小的区别是一个问题,怎么设计映射函数。

Loop Detection

检测一个链表是否有环,一方面使用哈希表可以计算得到,另外一方面使用快慢指针如果在遍历结束之前找到发生相交即可。

0 0
原创粉丝点击