算法题-数据结构(链表)

242 阅读5分钟

1.链表的逆输出

栈先进后出 用java实现

import java.util.ArrayList;

public class Solution {
    public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
        ArrayList<Integer>list=new ArrayList<>();
        ListNode p=listNode;
        while(p!=null){
            list.add(0,p.val);
            p=p.next;
        }
        return list;
    }
}

时间复杂度:O(n) 空间复杂度O(n)

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
*/

class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        std::stack<int> s1;
        ListNode* h=head;
        while(h!=NULL){
            s1.push(h->val);
            h=h->next;
        }
        vector<int>result;
        while(!s1.empty()){
            
            result.push_back(s1.top());
            s1.pop();
        }
        return result;
    }
};

作者:zhouying1999
链接:https://juejin.cn/post/6844904116863369230
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

2.链表中倒数第k个节点

快慢指针 时间复杂度O(n) 空间复杂度O(1)

链接:https://www.nowcoder.com/questionTerminal/529d3ae5a407492994ad2a246518148a?answerType=1&f=discussion
来源:牛客网

/*
public class ListNode {
    int val;
    ListNode next = null;
 
    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode FindKthToTail(ListNode head,int k) {
        if(head == null || k ==0 ){
            return null;
        }
 
        ListNode slow=head;
        ListNode fast=head;
        for(int i=0;i<k;i++){
            if(fast==null){
                return null;
            }
            fast=fast.next;
 
        }
        while(fast!=null){
            slow=slow.next;
            fast=fast.next;
        }
 
        return slow;
 
    }
}

3.反转链表

时间复杂度O(n) 空间复杂度O(1)

链接:https://www.nowcoder.com/questionTerminal/75e878df47f24fdc9dc3e400ec6058ca?answerType=1&f=discussion
来源:牛客网

/*
public class ListNode {
    int val;
    ListNode next = null;
 
    ListNode(int val) {
        this.val = val;
    }
}*/
public class Solution {
    public ListNode ReverseList(ListNode head) {
         // 判断链表为空或长度为1的情况
        if(head == null || head.next == null){
            return head;
        }
        ListNode pre = null; // 当前节点的前一个节点
        ListNode next = null; // 当前节点的下一个节点
        while( head != null){
            next = head.next; // 记录当前节点的下一个节点位置;
            head.next = pre; // 让当前节点指向前一个节点位置,完成反转
            pre = head; // pre 往右走
            head = next;// 当前节点往右继续走
        }
        return pre;
    }
}

4.合并两个排序的链表

sollution1 用一个新的指针

时间复杂度O(n) 空间复杂度O(1)

链接:https://www.nowcoder.com/questionTerminal/d8b6b4358f774294a89de2a6ac4d9337?answerType=1&f=discussion
来源:牛客网

public class Solution {
    public ListNode Merge(ListNode list1,ListNode list2) {
        ListNode h = new ListNode(-1);
        ListNode cur = h;
        while(list1 != null && list2 !=null){
            if(list1.val<=list2.val){
                cur.next = list1;
                list1 = list1.next;
            }else{
                cur.next = list2;
                list2 = list2.next;
            }
            cur = cur.next;
        }
        if(list1!=null) cur.next = list1;
        if(list2!=null) cur.next = list2;
        return h.next;
    }
}

sollution2 递归

时间复杂度O(n) 空间复杂度O(1)

链接:https://www.nowcoder.com/questionTerminal/d8b6b4358f774294a89de2a6ac4d9337?answerType=1&f=discussion
来源:牛客网

//递归
public ListNode Merge1(ListNode list1, ListNode list2) {
    if (list1 == null) {
        return list2;
    } else if (list2 == null) {
        return list1;
    }else{
        if(list1.val<list2.val){
            list1.next=Merge1(list1.next, list2);
            return list1;
        }else {
            list2.next=Merge1(list1, list2.next);
            return list2;
        }
    }
}

5.复杂链表的复制

hashmap存

时间复杂度O(n) 空间复杂度O(n)

链接:https://www.nowcoder.com/questionTerminal/f836b2c43afc4b35ad6adc41ec941dba?answerType=1&f=discussion
来源:牛客网

class RandomListNode {
    int label;
    RandomListNode next = null;
    RandomListNode random = null;
 
    RandomListNode(int label) {
        this.label = label;
    }
}
 
class Solution {
    public RandomListNode Clone(RandomListNode pHead)
    {
        if (pHead == null) {
            return pHead;
        }
        RandomListNode p1 = pHead;
        RandomListNode p2 = pHead;
        HashMap<RandomListNode, RandomListNode> map = new HashMap<>();
        while (p1 != null) {
            map.put(p1, new RandomListNode(p1.label));
            p1 = p1.next;
        }
 
        while (p2 != null) {
            if (p2.next != null) {
                map.get(p2).next = map.get(p2.next);
            } else {
                map.get(p2).next = null;
            }
            map.get(p2).random = map.get(p2.random);
            p2 = p2.next;
        }
        return map.get(pHead);
    }
}

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

线索:公共表尾

先算出长度差 让长的先走这个长度差 再两个一起走

跳出循环标志:两个指针的next相等

时间复杂度O(n) 空间复杂度O(1)

链接:https://www.nowcoder.com/questionTerminal/6ab1d9a29e88450685099d45c9e31e46?f=discussion
来源:牛客网

class Solution {
public:
    ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2) {
        int len1 = findListLenth(pHead1);
        int len2 = findListLenth(pHead2);
        if(len1 > len2){
            pHead1 = walkStep(pHead1,len1 - len2);
        }else{
            pHead2 = walkStep(pHead2,len2 - len1);
        }
        while(pHead1 != NULL){
            if(pHead1 == pHead2) return pHead1;
            pHead1 = pHead1->next;
            pHead2 = pHead2->next;
        }
        return NULL;
    }
     
    int findListLenth(ListNode *pHead1){
        if(pHead1 == NULL) return 0;
        int sum = 1;
        while(pHead1 = pHead1->next) sum++;
        return sum;
    }
     
    ListNode* walkStep(ListNode *pHead1, int step){
        while(step--){
            pHead1 = pHead1->next;
        }
        return pHead1;
    }
}; 

7.链表中环的入口结点

时间复杂度O(n) 空间复杂度O(1)

链接:https://www.nowcoder.com/questionTerminal/253d2c59ec3e4bc68da16833f79a38e4?answerType=1&f=discussion
来源:牛客网

public class Solution {
 
    public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        if(pHead == null || pHead.next == null){
            return null;
        }
 
        ListNode fast = pHead;
        ListNode slow = pHead;
 
        while(fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
            if(fast == slow){
                ListNode slow2 = pHead;
                while(slow2 != slow){
                    slow2 = slow2.next;
                    slow = slow.next;
                }
                return slow2;
            }
        }
        return null;
 
    }
}

8.删除链表的重复结点

用两个指针 遍历时同时删除

时间复杂度:O(n) 空间复杂度:O(1)

链接:https://www.nowcoder.com/questionTerminal/fc533c45b73a41b0b44ccba763f866ef?answerType=1&f=discussion
来源:牛客网

public class Solution {
    public ListNode deleteDuplication(ListNode pHead){
        if(pHead == null || pHead.next == null){
            return pHead;
        }
        // 自己构建辅助头结点
        ListNode head = new ListNode(Integer.MIN_VALUE);
        head.next = pHead;
        ListNode pre = head;
        ListNode cur = head.next;
        while(cur!=null){
            if(cur.next != null && cur.next.val == cur.val){
                // 相同结点一直前进
                while(cur.next != null && cur.next.val == cur.val){
                    cur = cur.next;
                }
                // 退出循环时,cur 指向重复值,也需要删除,而 cur.next 指向第一个不重复的值
                // cur 继续前进
                cur = cur.next;
                // pre 连接新结点
                pre.next = cur;
            }else{
                pre = cur;
                cur = cur.next;
            }
        }
        return head.next;
    }
}

9.两数相加(链表版)

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode dummyHead=new ListNode(0);
        ListNode p1=l1,p2=l2,cur=dummyHead;
        int carry=0;
        int sum=0;
        while(p1!=null||p2!=null){
            int x=(p1==null)?0:p1.val;
            int y=(p2==null)?0:p2.val;
            sum=carry+x+y;
            carry=sum/10;
            cur.next=new ListNode(sum%10);
            cur=cur.next;
            if(p1!=null)p1=p1.next;
            if(p2!=null)p2=p2.next;
        }
        if(carry!=0){
            cur.next=new ListNode(carry);
        }
        return dummyHead.next;
    }
}

增加新的空间

10.两两交换链表中的节点

其实本质还是考链表的操作

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode swapPairs(ListNode head) {
        ListNode dummyhead=new ListNode(-1);
        dummyhead.next=head;
        ListNode preNode=dummyhead;
        while(head!=null&&head.next!=null){
            ListNode firstNode=head;
            ListNode secondNode=head.next;

            preNode.next=secondNode;
            firstNode.next=secondNode.next;
            secondNode.next=firstNode;

            preNode=firstNode;
            head=firstNode.next;

        }
        return dummyhead.next;
    }
}

要注意的是:要设一个prenode连接到secondnode上

11.删除排序链表的重复元素

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode dummyhead=new ListNode(-1);
        dummyhead.next=head;
        ListNode pre=dummyhead;
        ListNode cur=head;
        int flag=0;
        while(pre!=null){
            while(pre!=dummyhead&&cur!=null&&cur.val==pre.val){
               flag=1;
               cur=cur.next;
            }
            if(flag==1){
                pre.next=cur;
                flag=0;
                pre=cur;
                if(cur!=null)cur=cur.next;
            }else{
                pre=cur;
                if(cur!=null)cur=cur.next;
            }
        }
        return dummyhead.next;
    }
}

12.删除排序链表中的重复元素plus

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        ListNode dummyhead=new ListNode(0);
        dummyhead.next=head;
        ListNode pre=dummyhead;
        ListNode cur=head;
        int flag=0;
        while(pre.next!=null){
            while(cur.next!=null&&cur.next.val==pre.next.val){
               flag=1;
               cur=cur.next;
            }
            if(flag==1){
                pre.next=cur.next;
                flag=0;
                cur=cur.next;
            }else{
                pre=cur;
                if(cur.next!=null)cur=cur.next;
            }
        }
        return dummyhead.next;
    }
}