【LeetCode】链表系列(排序)

19. Remove Nth Node From End of List

题目:移除单链表的倒数第n个节点(仅限一次遍历)

思路:Two Pointer——用两个节点框成长度为n大小的窗,窗移动到链表末尾时,即知道倒数第n个位置。这里要注意头结点的设置,可以有效处理需要移除头结点的情况。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        if(head == null) return null;
        ListNode pre = new ListNode(0);
        pre.next = head;
        ListNode p = pre;
        int count = 0;
        while(p.next != null && count < n){
            p = p.next;
            count++;
        }
        if(p.next == null) return head.next;
        while(p.next != null){
            p = p.next;
            pre = pre.next;
        }
        pre.next = pre.next.next;
        return head;
    }
}


阿里二面被问到的题,当时用遍历两次的方法来做的。后来也没用头结点,分情况讨论的,代码比较复杂。

21. Merge Two Sorted Lists

题目:输入两个有序链表,输出合并之后依然有序的链表。

思路:比较大小值,然后往后移,很直接的做法,加了head节点,发现head节点真的很好用。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if(l1 == null) return l2;
        if(l2 == null) return l1;
        ListNode head = new ListNode(0);
        ListNode p = head;
        while(l1 != null && l2 != null){
            if(l1.val <= l2.val){
                p.next = l1;
                l1 = l1.next;
            }
            else{
                p.next = l2;
                l2 = l2.next;
            }
            p = p.next;
        }
        if(l1 != null){
            p.next = l1;
        }
        if(l2 != null){
            p.next = l2;
        }
        return head.next;
    }
}

看了其他的解法,都是用递归做的很简单,值得学习。

public ListNode mergeTwoLists(ListNode l1, ListNode l2){
		if(l1 == null) return l2;
		if(l2 == null) return l1;
		if(l1.val < l2.val){
			l1.next = mergeTwoLists(l1.next, l2);
			return l1;
		} else{
			l2.next = mergeTwoLists(l1, l2.next);
			return l2;
		}
}


88. Merge Sorted Array

题目:在一个数组上合并两个数组(长度足够),使其合并后依然有序,

思路:与21题思路完全一致,链表换成数组而已,这里从大数开始比较,很简单。

public class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int i = m-1, j = n-1, k = m+n-1; 
        while(i >= 0 && j >= 0){
            if(nums1[i] > nums2[j]){
                nums1[k--] = nums1[i];
                i--;
            }
            else{
                nums1[k--] = nums2[j];
                j--;
            }
        }
        while(j >= 0){
            nums1[k--] = nums2[j--];
        }
    }
}


23. Merge k Sorted Lists

题目:合并k个有序链表,合并之后仍有序。

思路:分治+递归——在21题的基础上加上分治的思想,即将链表数组分割到每两个节点进行比较和拼接。递归是从大往小并,从小往大并的方法比较复杂,不可取。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        return partion(lists, 0, lists.length-1);
    }
    public ListNode partion(ListNode[] lists, int left, int right){
        if(left == right) return lists[left];
        else if(left < right){
            int mid = (left+right)/2;
            ListNode l1 = partion(lists, left, mid);
            ListNode l2 = partion(lists, mid+1, right);
            return merge(l1, l2);
        }
        else{
            return null;
        }
    }
    public ListNode merge(ListNode l1, ListNode l2){
        if(l1 == null) return l2;
        if(l2 == null) return l1;
        if(l1.val <= l2.val){
            l1.next = merge(l1.next, l2);
            return l1;
        }
        else{
            l2.next = merge(l1, l2.next);
            return l2;
        }
    }
}


24. Swap Nodes in Pairs

题目:两两交换节点

思路:设置前节点、p节点和后节点,按顺序进行交换即可,设置一个头结点会更加简单。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode swapPairs(ListNode head) {
        if(head == null || head.next == null) return head;
        ListNode pre = new ListNode(0);
        pre.next = head;
        head = pre;
        ListNode p = pre.next;
        while(p != null && p.next != null){
            ListNode next = p.next.next;
            pre.next = p.next;
            p.next.next = p;
            p.next = next;
            pre = p;
            p = next;
        }
        return head.next;
    }
}


附上递归的解法:

public class Solution {
    public ListNode swapPairs(ListNode head) {
        if ((head == null)||(head.next == null))
            return head;
        ListNode n = head.next;
        head.next = swapPairs(head.next.next);
        n.next = head;
        return n;
    }
}

25. Reverse Nodes in k-Group

题目:以k个节点为一组进行反转

思路:递归——先遍历k次,看是否足够k个节点,不足直接返回头结点,足够对该k个节点进行反转,将该k个节点后面的节点递归操作后,设为pre节点。然后对这k个节点进行反转。注意最后返回pre节点。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        if(head == null || head.next == null) return head;
        ListNode p = head;
        for(int i = 0; i< k; i++){
            if(p == null) return head;
            p = p.next;
        }
        ListNode pre = reverseKGroup(p, k);
        p = head;
        for(int i = 0; i < k; i++){
            ListNode next = p.next;
            p.next = pre;
            pre = p;
            p = next;
        }
        return pre;
    }
}

61. Rotate List 

题目:与旋转数组类似,在倒数第n个位置旋转链表

思路:用了与19题类似的方法,先找到需要旋转的位置,这里n如果大于链表长度,需要取模。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode rotateRight(ListNode head, int k) {
        if(head == null || head.next == null) return head;;
        int i = 0;
        ListNode p = new ListNode(0);
        ListNode q = p;
        p.next = head;
        while(i < k){
            if(p.next == null) {
                k = k%i;
                p = q;
                i = 0;
                continue;
            }
            p = p.next;
            i++;
        }
        if(p.next == null) return head;
        while(p.next != null){
            p = p.next;
            q = q.next;
        }
        p.next = head;
        ListNode temp = q.next;
        q.next = null;
        return temp;
    }
}

其实超长的时候,就已经知道链表长度了,可以算出值来,好像更简单一些。

public ListNode rotateRight(ListNode head, int n) {
    if (head==null||head.next==null) return head;
    ListNode dummy=new ListNode(0);
    dummy.next=head;
    ListNode fast=dummy,slow=dummy;

    int i;
    for (i=0;fast.next!=null;i++)//Get the total length 
    	fast=fast.next;
    
    for (int j=i-n%i;j>0;j--) //Get the i-n%i th node
    	slow=slow.next;
    
    fast.next=dummy.next; //Do the rotation
    dummy.next=slow.next;
    slow.next=null;
    
    return dummy.next;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值