目录

  • 前言
  • 正文
  • 1. 二维数组中的查找
  • 2. 从尾到头打印链表
  • 3. 反转链表
  • 4. 两个链表的第一个公共结点
  • 5. 链表中环的入口节点
  • 6. 链表中倒数最后k个结点
  • 7. 复杂链表的复制
  • 8. 删除链表中重复的节点
  • 参考

前言

正文

1. 二维数组中的查找

题目

牛客java高薪求职项目 牛客网offer show_牛客java高薪求职项目

code

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
    //思路:从最左下开始查找,大于该target就往右走,小于就往上走。总能找到的
        int rows = array.size();
        int cols = array[0].size();
        int i = rows-1;
        int j = 0;
        while(i>=0&&j<cols)
        {
            if(array[i][j]>target)
            {
                i--;
            }
            else if(array[i][j]<target)
            {
                j++;
            }
            else if(array[i][j]==target)
            {
                return true;
            }
        }
        return false;
    }
};

2. 从尾到头打印链表

题目

牛客java高薪求职项目 牛客网offer show_结点_02

方法一:采用递归的方式存储从尾到头的值。

code

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        vector<int> value;
        if(head!=NULL)
        {
            value.insert(value.begin(),head->val);//在begin的位置插入head->val
            if(head->next!=NULL)
            {
                vector<int> tempVec = printListFromTailToHead(head->next);//这个返回的就是head后面所有的值都插入到value的最前面的数组
                if(tempVec.size()>0)
                    value.insert(value.begin(),tempVec.begin(),tempVec.end());
            }
            
        }
        return value;
    }
};

方法二:采用栈的方式存储从尾到头的值code

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

3. 反转链表

题目

牛客java高薪求职项目 牛客网offer show_刷题_03

code

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* ReverseList(ListNode* head) {
        if(head==nullptr)
            return nullptr;
        ListNode* node = head;
        ListNode* pre = NULL;
        ListNode* next;
        ListNode* newHead = NULL;
        while(node)
        {
            next = node->next;
            if(next==NULL)
                newHead = node;
            node->next = pre;
            pre = node;
            node = next;
        }
        return newHead;
    }
};

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

题目

牛客java高薪求职项目 牛客网offer show_刷题_04

方法一:

code

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* head1, ListNode* head2) {
        if(head1==nullptr||head2 ==nullptr)
            return nullptr;
        ListNode *node1 = head1;
        ListNode *node2 = head2;
        while(node1!=node2)
        {
            node1=node1?node1->next:head2;//注意head1代表是第一个链表的非公共部分
            node2=node2?node2->next:head1;//head2代表的是第二个链表的非公共部分
        }
        return node1;
    }
};

方法二:code

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode* head1, ListNode* head2) {
        
        ListNode* p1 = head1;
        ListNode* p2 = head2;
        while(p1!=p2)
        {
            if(p1)
                p1 = p1->next;
            if(p2)
                p2 = p2->next;
            if(p1!=p2)//这个判定条件是必要的。
            {
                 if(p1==NULL)
                { 
                    p1 = head2;
                 }  
                if(p2==NULL)
                {
                    p2 = head1;
                }
            }    
        }
        return p1;
    }
};

5. 链表中环的入口节点

题目

牛客java高薪求职项目 牛客网offer show_算法_05

code

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* head) {
         ListNode *fast,*slow;
        slow = fast = head;
        while(slow!=NULL&&fast)
        {
            slow = slow->next;
            fast = fast->next;
            if(fast)//要注意这个地方,是有可能第二个测试案例十空的情况的。
                fast = fast->next;
            else
                break;
            if(slow==fast)
                break;
        }
        if(slow==NULL||fast==NULL)
            return NULL;
        //这个node1所指的地点一般就是相遇点
        //有一个等式,相遇点到入口点的距离等于头节点到入口点的距离
        ListNode* ptr1= head;
        ListNode* ptr2 = slow;
        while(ptr1!=ptr2)
        {
            ptr1 = ptr1->next;
            ptr2 = ptr2->next;
        }
        return ptr1;
    }
};

6. 链表中倒数最后k个结点

题目

牛客java高薪求职项目 牛客网offer show_牛客java高薪求职项目_06

code

/**
 * struct ListNode {
 *	int val;
 *	struct ListNode *next;
 *	ListNode(int x) : val(x), next(nullptr) {}
 * };
 */
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param pHead ListNode类 
     * @param k int整型 
     * @return ListNode类
     */
    ListNode* FindKthToTail(ListNode* head, int k) {
        if(head==NULL)
            return NULL;
        ListNode* node1 = head;
        ListNode* node2 = head;
        while(k--)
        {
            if(node1==NULL)
                return NULL;
            node1 = node1->next;
        }

        while(node2&&node1)//直到node1走到Null的时候,就证明慢指针已经走到对应的位置了
        {
            node1 = node1->next;
            node2 = node2->next;
        }
        
        return node2;
        
    }
};

7. 复杂链表的复制

  1. 题目
  2. 代码code
/*
struct RandomListNode {
    int label;
    struct RandomListNode *next, *random;
    RandomListNode(int x) :
            label(x), next(NULL), random(NULL) {
    }
};
*/
class Solution {
public:
    map<RandomListNode*,RandomListNode*> map;
    RandomListNode* Clone(RandomListNode* head) {
        if(head==nullptr)
            return nullptr;
        RandomListNode* node = head;
        while(node)
        {
            map[node] = new RandomListNode(node->label);
            node = node->next;
        }
        node = head;
        while(node)
        {
            map[node]->next = map[node->next];
            map[node]->random = map[node->random];
            node = node->next;
        }
        return map[head];
    }
};

8. 删除链表中重复的节点

题目

牛客java高薪求职项目 牛客网offer show_结点_07

方法一

code

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* head) {
        //首先利用好其实排序的这个特点
        if(head==nullptr)
            return nullptr;
        ListNode* pre = NULL;
        ListNode* node = head;
        ListNode* next;
        if(node)
            next = node->next;
        while(next)
        {
            if(node->val!=next->val)
            {
                pre = node;
                node = next;
                next = next->next;
            }
            else
            {
                while(next&&node->val==next->val)//不管怎么样,只要再next循环里面用到指针,前面的那个数一定要做防护,不然会出现段越界
                {
                    next = next->next;
                }
                
                while(node&&node!=next)
                {
                    ListNode* tmp = node->next;;
                    delete node;
                    node = tmp;
                }//这个while循环出来后,node就已经在Next的位置了
                if(pre==NULL)
                    head = node;
                else
                {
                    pre->next = node;
                }
                if(next)
                    next = next->next;
                  
            }
        }
        return head;
    }
};

方法二:递归法code

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* head) {
        if(head==nullptr||head->next ==nullptr)
        {
            return head;
        }
        if(head->val==head->next->val)//这个操作是先删除前面头节点的几个元素都相同的情况
        {
            ListNode* p = head->next->next;
            while(p!=nullptr&&p->val==head->val)
            {
                p = p->next;
            }
            head = p;
            return deleteDuplication(head);
        }
        head->next = deleteDuplication(head->next);//相当于是一个节点连上另一个跟自身值相等的元素
        return head;
    }
};