数据结构-线性表

来源:互联网 发布:暗黑破坏神2画面优化 编辑:程序博客网 时间:2024/06/14 09:07

算法题主要来自剑指offer上面的题目,本章主要是重新复习下线性表及其相关的算法题。

二维数组中的查找


在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

class Solution {public:    bool Find(vector<vector<int> > array,int target) {        bool isFind = false;        if (array.size() == 0) {            return isFind;        }        int currentRow = 0;        int currentColumn = array[0].size() - 1;        while (currentRow <= array.size()-1 && currentColumn >= 0) {            vector<int> rowVector = array[currentRow];            if (rowVector[currentColumn] > target) {                currentColumn--;            }else if (rowVector[currentColumn] < target){                currentRow++;            }else{                // 相等,说明找到                isFind = true;                return isFind;            }        }        return isFind;            }};

从尾到头打印链表

输入一个链表,从尾到头打印链表每个节点的值。

输入描述

输入为链表的表头

输出描述

输出为需要打印的“新链表”的表头

/***  struct ListNode {*        int val;*        struct ListNode *next;*        ListNode(int x) :*              val(x), next(NULL) {*        }*  };*/class Solution {public:    vector<int> printListFromTailToHead(struct ListNode* head) {          stack<int> stack;    vector<int> result;    ListNode *pNode = head;    if (pNode == NULL) {        return result;    }    while (pNode!= NULL) {        stack.push(pNode->val);        pNode = pNode->next;    }    while (!stack.empty()) {        result.push_back(stack.top());        stack.pop();    }    return result;    }};

链表中环的入口结点


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

/*struct ListNode {    int val;    struct ListNode *next;    ListNode(int x) :        val(x), next(NULL) {    }};*/class Solution {public:/** *  找出两个快慢结点相遇的结点 * *  @param pHead <#pHead description#> * *  @return <#return value description#> */ListNode* meetNode(ListNode* pHead){    // 慢结点,每次移动1步    ListNode *pSlowNode = pHead;    // 快结点,每次移动2步    ListNode *pFastNode = pHead->next;    if (pHead == NULL) {        return NULL;    }    if (pHead->next == NULL) {        return NULL;    }    while (pSlowNode != pFastNode) {        pSlowNode = pSlowNode->next;        pFastNode = pFastNode->next->next;    }    return pSlowNode;}/** *  求出头结点到相遇结点的距离 * *  @param pHead     <#pHead description#> *  @param pMeetNode <#pMeetNode description#> * *  @return <#return value description#> */int distanceFormHeadToMeetNode(ListNode* pHead,ListNode* pMeetNode){    int distance = 0;    ListNode* pNode = pHead;    while (pNode != pMeetNode) {        distance++;        pNode = pNode->next;    }    return distance;}ListNode* EntryNodeOfLoop(ListNode* pHead){    if (pHead == NULL) {        return NULL;    }    if (pHead->next == NULL) {        return NULL;    }    ListNode* pNode1 = pHead;    ListNode* pNode2 = pHead->next;    ListNode* pMeetNode = meetNode(pHead);    int distance = distanceFormHeadToMeetNode(pHead, pMeetNode);    // pHead2先移动distance个距离    while (distance != 0) {        pNode2 = pNode2->next;        distance--;    }    while (pNode1 != pNode2) {        pNode1 = pNode1->next;        pNode2 = pNode2->next;    }    return pNode1;}};

反转链表


输入一个链表,反转链表后,输出链表的所有元素。

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

链表中倒数第k个结点


输入一个链表,输出该链表中倒数第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) {        // 先求出链表长度length,倒数第k个结点相当于第 length - k + 1个结点        ListNode* pNode = pListHead;    if (pListHead == NULL) {        return NULL;    }    int length = 1;    while (pNode != NULL) {        length++;        pNode = pNode->next;    }    pNode = pListHead;    ListNode *pFindNode = NULL;    // 取得了链表的长度length后,找到第 length - k + 1    int count = 1;    while (pNode != NULL) {        count++;        if (count == length - k + 1) {            pFindNode = pNode;            break;        }        pNode = pNode->next;    }    return pFindNode;    }};

只需遍历一次的算法(使用两个指针)(注意代码的鲁棒性

/*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 == NULL || k== 0) {            return NULL;        }        ListNode* pAheadNode = pListHead;        ListNode* pBehind = pListHead;        for (int i = 0; i < k-1; i++) {             // pAheadNode向前移动            if (pAheadNode->next != NULL) {                pAheadNode = pAheadNode->next;            }else{                return NULL;            }        }        while (pAheadNode->next != NULL) {            pBehind = pBehind->next;            pAheadNode = pAheadNode->next;        }        return pBehind;    }};

合并两个排序的链表(注意采用递归的思想)


输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

不用递归的思想

/*struct ListNode {    int val;    struct ListNode *next;    ListNode(int x) :            val(x), next(NULL) {    }};*/class Solution {public:    ListNode* Merge(ListNode* pHead1, ListNode* pHead2)    {    ListNode* pHead = NULL;    ListNode* pLast = NULL;    if (pHead1 == NULL && pHead2 == NULL) {        return NULL;    }else if (pHead1 == NULL && pHead2 != NULL){        return pHead2;    }else if (pHead1 != NULL && pHead2 == NULL){        return pHead1;    }else{        ListNode* pNode1 = pHead1;        ListNode* pNode2 = pHead2;        // 先找出链表的头结点        if (pNode1->val <= pNode2->val) {            pHead = pNode1;            pNode1 = pNode1->next;        }else{            pHead = pNode2;            pNode2 = pNode2->next;        }        pLast = pHead;        while (pNode1 != NULL || pNode2 != NULL) {            ListNode* pNode = NULL;            if (pNode1 == NULL) {                pLast->next = pNode2;                return pHead;            }            if (pNode2 == NULL) {                pLast->next = pNode1;                return pHead;            }            if (pNode1->val <= pNode2->val) {                pNode = pNode1;                pNode1 = pNode1->next;            }else{                pNode = pNode2;                pNode2 = pNode2->next;            }            // 找到最小的结点后,最后一个结点指向该结点            pLast->next = pNode;            pLast = pNode;        }    }    return pHead;    }};

使用递归的思想

/*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 == NULL) {        return pHead2;    }    if (pHead2 == NULL) {        return pHead1;    }    ListNode* pHead = NULL;    if (pHead1->val < pHead2->val) {        pHead = pHead1;        pHead->next = Merge(pHead1->next, pHead2);    }else{        pHead = pHead2;        pHead->next = Merge(pHead1, pHead2->next);    }    return pHead;    }};

复杂链表的复制


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

/*struct RandomListNode {    int label;    struct RandomListNode *next, *random;    RandomListNode(int x) :            label(x), next(NULL), random(NULL) {    }};*/class Solution {public:RandomListNode* Clone(RandomListNode* pHead)    {        if(!pHead) return NULL;        RandomListNode *currNode = pHead;        while(currNode){            RandomListNode *node = new RandomListNode(currNode->label);            node->next = currNode->next;            currNode->next = node;            currNode = node->next;        }        currNode = pHead;        while(currNode){            RandomListNode *node = currNode->next;            if(currNode->random){                               node->random = currNode->random->next;            }            currNode = node->next;        }        //拆分        RandomListNode *pCloneHead = pHead->next;        RandomListNode *tmp;        currNode = pHead;        while(currNode->next){            tmp = currNode->next;            currNode->next =tmp->next;            currNode = tmp;        }        return pCloneHead;    }};

两个链表的第一个公共结点


输入两个链表,找出它们的第一个公共结点。

/*struct ListNode {    int val;    struct ListNode *next;    ListNode(int x) :            val(x), next(NULL) {    }};*/class Solution {public:    ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2) {         if (pHead1 == NULL || pHead2 == NULL) {        return NULL;    }    // 分别计算两个链表的长度    int length1 = 1;    int length2 = 1;    ListNode* pNode1 = pHead1;    ListNode* pNode2 = pHead2;    while (pNode1->next != NULL) {        length1++;        pNode1 = pNode1->next;    }    while (pNode2->next != NULL) {        length2++;        pNode2 = pNode2->next;    }    // 比较两个链表的长度    int distance = length1 - length2;    if (distance > 0) {        // 说明链表1的长度长,链表1先走distance步。        while (distance > 0) {            pHead1 = pHead1->next;            distance--;        }    }else{        // 链表2的长度长        distance = -distance;        while (distance > 0) {            pHead2 = pHead2->next;            distance--;        }    }    ListNode* commonNode = NULL;    // 此时两个链表走的长度是相同的,可以同时遍历    while (pHead1 != pHead2 && pHead1 != NULL && pHead2 != NULL) {        pHead1 = pHead1->next;        pHead2 = pHead2->next;    }    commonNode = pHead1;    return commonNode;    }};

删除链表中重复的结点


在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

/*struct ListNode {    int val;    struct ListNode *next;    ListNode(int x) :        val(x), next(NULL) {    }};*/// 递归class Solution {public:    ListNode* deleteDuplication(ListNode* pHead)    {        if (pHead==NULL)            return NULL;        if (pHead!=NULL && pHead->next==NULL)            return pHead;        ListNode* current;        if ( pHead->next->val==pHead->val){            current=pHead->next->next;            while (current != NULL && current->val==pHead->val)                current=current->next;            return deleteDuplication(current);                             }        else {            current=pHead->next;            pHead->next=deleteDuplication(current);            return pHead;        }        }};

旋转数组的最小数字


把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

0 0
原创粉丝点击