链表

1、链表相加

题目:

给定两个链表,分别表示两个非负整数,逆序存储在链表中,计算两个数的和,并返回链表头指针,如:
输入:2->4->3、5->6->4,输出7->0->8

思路及代码:

public ListNode addTwoNumbers(ListNode l1, ListNode l2){
  // 堆栈思路,首先将list都放入stack中,再进行操作
    Stack<Integer> s1 = new Stack<>();
    Stack<Integer> s2 = new Stack<>();

    while(s1 != null){
        s1.push(l1.val);
        l1 = l1.next;
    }
    while(s2 != null){
        s2.push(l2.val);
        l2 = l2.next;
    }

    int num = 0;
    ListNode list = new ListNode(0);
    while(!s1.empty() || !s2.empty()){
        if(!=s1.empty()){
            sum += s1.pop();
        }
        if(!=s2.empty()){
            sum += s2.pop();
        }
        list.val = sum % 10;
        ListNode head = new ListNode(sum / 10);
        head.next = list;
        list = head;
        sum /= 10;
    }
    return list.val == 0 ? list.next : list;
}

 

class solution{

    public ListNode addTwoNumbers(ListNode l1, ListNode l2){
        l1 = reverseList();
        l2 = reverseList();
        ListNode sumReversed = addTwoNumbersReversed(l1, l2);
        reverseList(l1);
        reverseList(l2);
        return reverseList(sumReversed);
    }

    public ListNode reverseList(ListNode head){
        ListNode curr = head;
        ListNode next;
        ListNode prev = null;
        while(cuur != null){
            // 先建立连接,再反指翻转,再后移
            next = curr.next;
            curr.next = prev;
            prev = curr;
            curr = next;
        }
    }

    public ListNode addTwoNumbersReversed(ListNode l1, ListNode l2){
        ListNode head = new ListNode(0);
        ListNode curr = head;
        int carry = 0;
        while(l1 != null || l2 != null carry == 1){
            int sum = (l1 == null ? 0 : l1.val) + (l2 == null ? 0 : l2.val) + carry;
            if(sum > 9){
                carry = 1;
                sum /= 10;
            }
            else{
                carry = 0;
            }
            curr.next = new ListNode(sum);
            curr = curr.next;
            if(l1 != null){
                l1 = l1.next;
            }
            if(l2 != null){
                l2 = l2.next;
            }
        }
        return head.next;
    }
}

 

class solution{
  // 递归
    public ListNode addTwoNumbers(ListNode l1, ListNode l2){
        if(l1 == null || l2 == null){
            return l1 == null ? l1 : l1;
        }
        return addTwoNumbers(l1, l2, 0);
    }

    public ListNode addTwoNumbers(ListNode l1, ListNode l2, int carry){
        if(l1 == null && l2==null){
            return carry == 0 ? null : new ListNode(1);
        }
        int num1 = l1 == null ? 0 : l1.val;
        int num2 = l2 == null ? 0 : l2.val;
        boolean flag = false;
        int sum = num1 + num2 + carry;
        if(sum > 9){
            flag = true;
            sum = sum - 10;
        }
        ListNode res = new ListNode(sum);
        res.next = addTwoNumbers(l1 == null ? l1 : l1.next, l2 == null ? l2 : l2.next, flag ? 1 : 0);
        return res;
    }
}

2、链表翻转(部分翻转)

题目:给定一个链表,翻转该链表从m到n位置,直接反转不申请新空间

思路及代码:

import util.ListNode;
import java.util.List;

public class listReverse {
  // 全部翻转,使用递归
    public ListNode reverseList(ListNode node){
        if(node == null || node.next == null){
            return node;
        }
        ListNode preNode = reverseList(node.next);
        node.next.next = node;  // 反转
        node.next = null;
        return preNode;
    }

  // 全部翻转,使用循环
    public ListNode reverseList_2(ListNode head){
        if(head == null){
            return null;
        }
        ListNode pre = null;
        ListNode next = null;
        while(head != null){
     // 避免断裂,先将后边的数据存入next
            next = head.next;
     // 将当前节点指向前节点
            head.next = pre;
     // 将当前节点和前节点向后移一位
            pre = head;
            head = next;
        }
    // 循环结束后,当前节点为空,最后一个节点为pre,为反转后的第一个节点,返回
        return pre;
    }

  // 部分翻转,使用头插法,基本思路是找到begin节点的前一个节点记为pre,从begin的下一个位置开始,
  // 插入到pre后边,并将传递过来节点的next节点指向begin,下一个仍然放到pre的后边,其next指向上一次传来的节点
  // 注:这里使用一个head节点,head节点的next指向链表的第一个节点
    public ListNode reverseList_3(ListNode head, int from, int to){
        ListNode preHead = new ListNode(0);
        preHead.next = head;
    // 定义curr节点,从prehead开始,找到第m-1个节点,作为curPre
        ListNode curr = preHead;
        for(int i = 1; i < from; i++){
            curr = curr.next;
        }
        ListNode curPre = curr;
        curr = curr.next;
        ListNode curNext = null;
        for(int i=from; i<to; i++){
            curNext = curr.next;
            curr.next = curNext.next;
            curNext.next = curPre.next;
            curPre.next = curNext;
        }
        return preHead.next;
    }
}

 

3、排序链表去重

题目:

(1) 给定排序的链表,删除重复的元素,只保留重复元素第一次出现的节点

(2) 若发现重复元素,则重复元素全部删除

思路及代码:

(1) 若p.next的值与p相等,则将p.next.next指向p,删除p.next,重复此过程,至链表尾端

// 此类问题的关键是链表是排好序的, 若链表没排好序则需要先排序后再进行去重操作
// 删除重复元素,保留第一次出现的元素
public static void DeleteDuplicateNode(ListNode head){
    ListNode pre = head;
    ListNode cur;
    while(pre != null){
        cur = pre.next;
        if(cur!=null && cur.val==pre.val){
            pre.next = cur.next;
        }
        else{
            pre = cur;
        }
    }
}

(2)若全删除,则准备pre,cur和next指针

// 问题变成重复元素全部删除
public static void DeleteDuplicateNodePlus(ListNode head){
    ListNode pre = head;
    head = pre.next;
    ListNode cur = head;
    ListNode next;
    boolean bDup;
    while(cur != null){
        next = cur.next;
        bDup = false;
        while(next!=null && (cur.val == next.val)){
            pre.next = next;
            cur = next;
            next = cur.next;
            bDup = true;
        }
        if(bDup){
            pre.next = next;
        }
        else{
            pre = cur;
        }
        cur = next;
    }
}

4、链表划分

题目:

给定一个链表和一个值x,将链表划分为大于x的部分和小于x的部分,且两部分保持原链表相对位置

思路及代码:

// 给定两个指针,小于x的添加到p1中,大于x的添加到p2中,最后将p2链接到p1的末端,时间复杂度O(N),空间复杂度O(1)
public static ListNode patition(ListNode head, int key){
    if(head == null){
        return null;
    }
    ListNode left = new ListNode(0);
    ListNode right = new ListNode(0);
    ListNode leftDummy = left;
    ListNode rightDummy = right;
    while(head!=null){
        if(head.val < key){
            left.next = head;
            left = head;
        }
        else{
            right.next = head;
            right = head;
        }
        head = head.next;
    }
    left.next = rightDummy.next;
    right.next = null;
    return leftDummy.next;
}

 实现2....待补充

5、单链公共节点问题

题目:

思路及代码:

6、链表重排序

题目:

Reorder List  链表重排序问题

将一个列表重新排列,例:

Given 1->2->3->4,  reorder it to 1->4->2->3.

Given 1->2->3->4->5,  reorder it to 1->5->2->4->3.

思路及代码:

7、打印两个链表的公共部分

8、判断链表是否为回文结构

posted @ 2019-02-27 18:04  Luckid  阅读(140)  评论(0编辑  收藏  举报