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、判断链表是否为回文结构