算法必刷系列之链表

算法必刷系列之链表

链表反转

public LinkedNode reverse(LinkedNode head){
    LinkedNode vhead = new LinkedNode(-1);
    vhead.next = head;
    LinkedNode current = head;
    while(current!=null){
        LinkedNode next = current.next;
        current.next = vhead.next;
        vhead.next = current;
        current = next;
    }
    return vhead.next;
}
public static LinkedNode reverse2(LinkedNode head){
    LinkedNode pre = null;
    LinkedNode current = head;
    while (current!=null){
        LinkedNode next = current.next;
        current.next = pre;
        pre = current;
        current = next;
    }
    return pre;
}

链表第一个公共子节点问题

ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    int lengthA = getLength(headA);
    int lengthB = getLength(headB);
    int abs = Math.max(lengthA,lengthB) - Math.min(lengthA,lengthB);
    if(lengthA>lengthB){
        for(int i=0;i<abs;i++){
            headA = headA.next;
        }
    }else if(lengthB>lengthA){
        for(int i=0;i<abs;i++){
            headB = headB.next;
        }
    }
    while(headA!=headB){
        headA = headA.next;
        headB = headB.next;
    }
    return headA;
}
public int getLength(ListNode head){
    int count = 0;
    ListNode current = head;
    while(current != null){
        count++;
        current = current.next;
    }
    return count;
}

判断回文链表

public boolean isPalindrome(ListNode head) {
    ListNode slow = head;
    ListNode fast = head;
    while(fast!=null && fast.next!=null){
        slow = slow.next;
        fast = fast.next.next;
    }
    ListNode reverseHead = reverse(slow);
    while(head!=slow){
        if(head.val!=reverseHead.val){
            return false;
        }
        head = head.next;
        reverseHead = reverseHead.next;
    }
    return true;
}

public ListNode reverse(ListNode head){
    ListNode pre = null;
    ListNode current = head;
    while(current!=null){
        ListNode next = current.next;
        current.next = pre;
        pre = current;
        current = next;
    }
    return pre;
}

合并有序链表

public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
    ListNode vhead = new ListNode(-1);
    ListNode iter = vhead;
    while(list1!=null&&list2!=null){
        ListNode node1 = list1;
        ListNode node2 = list2;
        if(list1.val<list2.val){
            iter.next = node1;
            iter = node1;
            list1 = list1.next;
        }else{
            iter.next = node2;
            iter = node2;
            list2 = list2.next;
        }
    }
    if(list1!=null){
        iter.next = list1;
    }else{
        iter.next = list2;
    }
    return vhead.next;
}

寻找中间节点

public ListNode middleNode(ListNode head) {
    ListNode slow = head;
    ListNode fast = head;
    while(fast!=null&&fast.next!=null){
        slow = slow.next;
        fast = fast.next.next;
    }
    return slow;
}

寻找倒数第K个元素

public ListNode getKthFromEnd(ListNode head){
	ListNode slow = head;
	ListNode fast = head;
	while(fast!=null&&k>0){
        fast = fast.next;
        k--;
    }
	while(fast!=null){
        fast = fast.next;
        slow = slow.next;
    }
	return slow;
}

旋转链表

public ListNode rotateRight(ListNode head, int k) {
    if(head==null || head.next==null || k<=0){
        return head;
    }
    ListNode current = head;
    int len = 0;
    while(current.next!=null){
        len++;
        current = current.next;
    }
    len++;
    k = k%len;
    if(k%len==0){
        return head;
    }
    ListNode K1Node = getKthFromEnd(head,k+1);
    ListNode KNode = K1Node.next;
    K1Node.next = null;
    current.next = head;
    return KNode;
}
public ListNode getKthFromEnd(ListNode head,int k){
    ListNode slow = head;
    ListNode fast = head;
    while(fast!=null&&k>0){
        fast = fast.next;
        k--;
    }
    while(fast!=null){
        fast = fast.next;
        slow = slow.next;
    }
    return slow;
}

移除链表元素

public ListNode removeElements(ListNode head, int val) {
    ListNode vhead = new ListNode(-1,head);
    ListNode current = vhead;
    while(current.next!=null){
        if(current.next.val == val){
            current.next = current.next.next;
        }else{
            current = current.next;
        }
    }
    return vhead.next;
}

删除链表倒数第n个节点

public ListNode removeNthFromEnd(ListNode head, int n) {
    ListNode vhead = new ListNode(-1,head);
    ListNode slow = vhead;
    ListNode fast = vhead;
    while(fast!=null&&n>=0){
        fast = fast.next;
        n--;
    }
    while(fast!=null){
        fast = fast.next;
        slow = slow.next;
    }
    slow.next = slow.next.next;
    return vhead.next;
}

删除链表中的重复元素(重复元素保留一个)

public ListNode deleteDuplicates(ListNode head) {
    ListNode current = head;
    while(current!=null&&current.next!=null){
        if(current.next.val == current.val){
            current.next = current.next.next;
        }else{
            current = current.next;
        }
    }
    return head;
}

删除链表中的重复元素(只保留出现一次的元素)

public ListNode deleteDuplicates(ListNode head) {
    ListNode vhead = new ListNode(-1,head);
    ListNode current = vhead;
    while(current.next!=null&&current.next.next!=null){
        if(current.next.val == current.next.next.val){
            int val = current.next.val;
            while(current.next!=null&&current.next.val == val){
                current.next = current.next.next;
            }
        }else{
            current = current.next;
        }
    }
    return vhead.next;
}

指定区间反转

public ListNode reverseBetween(ListNode head, int left, int right) {
    ListNode vhead = new ListNode(-1,head);
    ListNode current = vhead;
    for(int i=0;i<left-1;i++){
        current = current.next;
    }
    ListNode preNode = current;
    ListNode leftNode = current.next;
    for(int i=left;i<=right;i++){
        current = current.next;
    }
    ListNode rightNode = current;
    ListNode postNode = current.next;
    current.next = null;
    rightNode = reverse(leftNode);
    preNode.next = rightNode;
    leftNode.next = postNode;
    return vhead.next;
}
public ListNode reverse(ListNode head){
    ListNode pre = null;
    ListNode current = head;
    while(current!=null){
        ListNode next = current.next;
        current.next = pre;
        pre = current;
        current = next;
    }
    return pre;
}

两两交换链表中的节点

public ListNode swapPairs(ListNode head) {
    ListNode vhead = new ListNode(-1,head);
    ListNode current = vhead;
    while(current.next!=null&&current.next.next!=null){
        ListNode node1 = current.next;
        ListNode node2 = current.next.next;
        current.next = node2;
        node1.next = node2.next;
        node2.next = node1;
        current = node1;
    }
    return vhead.next;
}

链表加一

public ListNode plusOne(ListNode head) {
    head = reverse(head);
    ListNode current = head;
    int flag = 0;
    do {
        current.val += 1;
        flag = current.val / 10;
        current.val %= 10;
        current = current.next;
    } while (flag == 1 && current != null);
    head = reverse(head);
    if (flag == 1) {
        ListNode node = new ListNode(1);
        node.next = head;
        head = node;
    }
    return head;
}

public ListNode reverse(ListNode head) {
    ListNode pre = null;
    ListNode current = head;
    while (current != null) {
        ListNode next = current.next;
        current.next = pre;
        pre = current;
        current = next;
    }
    return pre;
}

链表加法

public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
    ListNode r1 = reverse(l1);
    ListNode r2 = reverse(l2);
    ListNode vhead = new ListNode(-1);
    ListNode current = vhead;
    int flag = 0;
    while(r1!=null||r2!=null||flag==1){
        int a = r1==null?0:r1.val;
        int b = r2==null?0:r2.val;
        int sum = a+b+flag;
        flag = sum/10;
        sum%=10;
        ListNode node = new ListNode(sum);
        current.next = node;
        current = node;
        if(r1!=null){
            r1=r1.next;
        }
        if(r2!=null){
            r2=r2.next;
        }
    }
    return reverse(vhead.next);
}

public ListNode reverse(ListNode head){
    ListNode pre = null;
    ListNode current = head;
    while(current!=null){
        ListNode next = current.next;
        current.next = pre;
        pre = current;
        current = next;
    }
    return pre;
}

判断链表是否有环

public boolean hasCycle(ListNode head) {
    ListNode fast = head;
    ListNode slow = head;
    while(fast!=null&&fast.next!=null){
        fast = fast.next.next;
        slow = slow.next;
        if(fast==slow){
            return true;
        }
    }
    return false;
}

带环链表环的入口

public ListNode detectCycle(ListNode head) {
    ListNode slow = head;
    ListNode fast = head;
    while(fast!=null&&fast.next!=null){
        fast=fast.next.next;
        slow = slow.next;
        if(fast==slow){
            break;
        }
    }
    if(fast==null||fast.next==null){
        return null;
    }
    fast = head;
    while(fast!=slow){
        fast = fast.next;
        slow = slow.next;
    }
    return slow;
}

K个一组反转链表

public ListNode reverseKGroup(ListNode head, int k) {
    //简化计算,先遍历获取链表长度
    int len = getLength(head);
    //计算需要反转的次数
    int n = len/k;
    //简历虚拟头节点
    ListNode vhead = new ListNode(-1);
    //current指向每次头插法插入的头节点
    ListNode current = vhead;
    //iter用于遍历给定链表
    ListNode iter = head;
    //n次反转
    for(int i=0;i<n;i++){
        //k个一组反转
        for(int j=0;j<k;j++){
            //记录需要遍历的下一个节点
            ListNode next = iter.next;
            //头插法进行节点插入
            iter.next = current.next;
            current.next = iter;
            //继续遍历
            iter = next;
        }
        //将current指向当前的最后一个节点,也是下次头插法的头节点
        for(int l=0;l<k;l++){
            current = current.next;
        }
    }
    //不足k个,直接拼接
    if(iter!=null){
        current.next = iter;
    }
    //返回k个一组反转后的链表
    return vhead.next;
}

public ListNode reverseKGroup(ListNode head, int k) {
    //为了方便插入,简历虚拟头节点
    ListNode vhead = new ListNode(-1);
    //pre指向拼接时的前一个节点
    ListNode pre = vhead;
    //计算反转次数
    int n = getLength(head)/k;
    //current用于遍历给定链表
    ListNode current = head;
    //n次反转
    for(int i=0;i<n;i++){
        //left指向反转前的第一个元素
        ListNode left = current;
        //找到当前的第K个元素
        for(int j=0;j<k-1;j++){
            current = current.next;
        }
        //right指向反转前的最后一个元素
        ListNode right = current;
        //post指向拼接时的后一个节点
        ListNode post = current.next;
        //right必须置空,否则后面的元素会一起反转
        right.next = null;
        //反转
        right = reverse(left);
        //拼接
        pre.next = right;
        left.next = post;
        //下次拼接时的前一个节点变成left
        pre = left;
        //下一次反转从post开始计数
        current = post;
    }
    //最后不足K个,直接拼接
    if(current!=null){
        pre.next = current;
    }
    //返回反转结果
    return vhead.next;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天不coding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值