算法入门-链表

判断回文链表

import java.util.Stack;

/**
 * 判断一个链表是否为回文结构
 * 【题目】 给定一个链表的头节点head,请判断该链表是否为回文结构。 
 * 例如: 1->2->1,返回true。 1->2->2->1,返回true。
 * 	   15->6->15,返回true。 1->2->3,返回false。
 * 进阶: 如果链表长度为N,时间复杂度达到O(N),额外空间复杂度达到O(1)。
 * @author Administrator
 *
 */
public class Palindrome {
	
	// need n extra space
	public static boolean isPalindrome1(Node head){
		if (head == null || head.next == null) {
			return true;
		}
		Stack<Node> help = new Stack<>();
		Node cur = head;
		while(cur != null) {
			help.push(cur);
			cur = cur.next;
		}
		while(head != null) {
			if(head.value != help.pop().value){
				return false;
			}
			head = head.next;
		}
		
		return true;
	}
	
	/* need n/2 extra space
	 * 1.当快指针到达链表末尾(链表节点为偶数时,尾部位置是链表长度减一)时,
	 * 慢指针处在中间位置(节点为偶数时,是右边部分)
	 * 2.从慢指针所指位置开始,将节点依次压入栈中
	 * 3.比较值是否相等
	 */
	public static boolean isPalindrome2(Node head) {
		if (head == null || head.next == null) {
			return true;
		}
		Node right = head.next;
		Node cur = head;
		while(cur.next != null && cur.next.next != null) {
			right = right.next;
			cur = cur.next.next;
		}
		Stack<Node> help = new Stack<>();
		while(right != null) {
			help.push(right);
			right = right.next;
		}
		
		while(!help.isEmpty()) {
			if(head.value != help.pop().value) {
				return false;
			}
			head = head.next;
		}
		
		return true;
	}
	
	/*
	 * need 0(1) extra space
	 * 1.慢指针指到中间位置时,将mid的next置为null,将mid->right部分的链表反转,
	 * 2.反转后即right->mid 跟 left->mid进行比较,
	 * 3.返回结果前将反转的链表反转回来
	 * */
	public static boolean isPalindrome3(Node head) {
		if(head == null || head.next == null) {
			return true;
		}
		Node n1 = head; // 慢指针(偶数时,遍历之后在left part最后一个节点,奇数时,是mid)
		Node n2 = head; // 快指针
		while(n2.next != null && n2.next.next != null) {
			n1 = n1.next; // n1 -> mid
			n2 = n2.next.next; // n2 -> end
		} // after while,n1 ->mid or left part last node
		
		n2 = n1.next; // n2 -> right part first node
		n1.next = null; // mid -> null
		Node n3 = null;
		while(n2 != null) { // reverse list
			n3 = n2.next;
			n2.next = n1;
			n1 = n2;
			n2 = n3;
		} // after while, n1 -> right part last node
		n3 = n1; // n3 -> save last node
		n2 = head; // n2 -> left part first node
		boolean res = true;
		while(n1 != null && n2 != null) {
			if(n1.value != n2.value) {
				res = false;
				break;
			}
			n1 = n1.next; // left -> mid
			n2 = n2.next; // right -> mid
		}
		n1 = n3.next; 
		n3.next = null;
		while(n1 != null) { // reserve list
			n2 = n1.next;
			n1.next = n3;
			n3 = n1;
			n1 = n2;
		}
		return res;
	}
	
	public static class Node {
		public int value;
		public Node next;
		
		public Node(int data) {
			this.value = data;
		}
	}
	
	public static void printLinkedList(Node head) {
		System.out.println("LinkedList:");
		while(head != null) {
			System.out.print(head.value + " ");
			head = head.next;
		}
		System.out.println();
	}
	
	// for test
	public static void main(String[] args) {

		Node head = null;
		printLinkedList(head);
		System.out.print(isPalindrome1(head) + " | ");
		System.out.print(isPalindrome2(head) + " | ");
		System.out.println(isPalindrome3(head) + " | ");
		printLinkedList(head);
		System.out.println("=========================");

		head = new Node(1);
		printLinkedList(head);
		System.out.print(isPalindrome1(head) + " | ");
		System.out.print(isPalindrome2(head) + " | ");
		System.out.println(isPalindrome3(head) + " | ");
		printLinkedList(head);
		System.out.println("=========================");

		head = new Node(1);
		head.next = new Node(2);
		printLinkedList(head);
		System.out.print(isPalindrome1(head) + " | ");
		System.out.print(isPalindrome2(head) + " | ");
		System.out.println(isPalindrome3(head) + " | ");
		printLinkedList(head);
		System.out.println("=========================");

		head = new Node(1);
		head.next = new Node(1);
		printLinkedList(head);
		System.out.print(isPalindrome1(head) + " | ");
		System.out.print(isPalindrome2(head) + " | ");
		System.out.println(isPalindrome3(head) + " | ");
		printLinkedList(head);
		System.out.println("=========================");

		head = new Node(1);
		head.next = new Node(2);
		head.next.next = new Node(3);
		printLinkedList(head);
		System.out.print(isPalindrome1(head) + " | ");
		System.out.print(isPalindrome2(head) + " | ");
		System.out.println(isPalindrome3(head) + " | ");
		printLinkedList(head);
		System.out.println("=========================");

		head = new Node(1);
		head.next = new Node(2);
		head.next.next = new Node(1);
		printLinkedList(head);
		System.out.print(isPalindrome1(head) + " | ");
		System.out.print(isPalindrome2(head) + " | ");
		System.out.println(isPalindrome3(head) + " | ");
		printLinkedList(head);
		System.out.println("=========================");

		head = new Node(1);
		head.next = new Node(2);
		head.next.next = new Node(3);
		head.next.next.next = new Node(1);
		printLinkedList(head);
		System.out.print(isPalindrome1(head) + " | ");
		System.out.print(isPalindrome2(head) + " | ");
		System.out.println(isPalindrome3(head) + " | ");
		printLinkedList(head);
		System.out.println("=========================");

		head = new Node(1);
		head.next = new Node(2);
		head.next.next = new Node(2);
		head.next.next.next = new Node(1);
		printLinkedList(head);
		System.out.print(isPalindrome1(head) + " | ");
		System.out.print(isPalindrome2(head) + " | ");
		System.out.println(isPalindrome3(head) + " | ");
		printLinkedList(head);
		System.out.println("=========================");

		head = new Node(1);
		head.next = new Node(2);
		head.next.next = new Node(3);
		head.next.next.next = new Node(2);
		head.next.next.next.next = new Node(1);
		printLinkedList(head);
		System.out.print(isPalindrome1(head) + " | ");
		System.out.print(isPalindrome2(head) + " | ");
		System.out.println(isPalindrome3(head) + " | ");
		printLinkedList(head);
		System.out.println("=========================");

	}
}

运行结果

LinkedList:

true | true | true | 
LinkedList:

=========================
LinkedList:
1 
true | true | true | 
LinkedList:
1 
=========================
LinkedList:
1 2 
false | false | false | 
LinkedList:
1 2 
=========================
LinkedList:
1 1 
true | true | true | 
LinkedList:
1 1 
=========================
LinkedList:
1 2 3 
false | false | false | 
LinkedList:
1 2 3 
=========================
LinkedList:
1 2 1 
true | true | true | 
LinkedList:
1 2 1 
=========================
LinkedList:
1 2 3 1 
false | false | false | 
LinkedList:
1 2 3 1 
=========================
LinkedList:
1 2 2 1 
true | true | true | 
LinkedList:
1 2 2 1 
=========================
LinkedList:
1 2 3 2 1 
true | true | true | 
LinkedList:
1 2 3 2 1 
=========================

复制含有随机指针节点的链表

import java.util.HashMap;
import java.util.Map;

/**
 * 复制含有随机指针节点的链表
 * 【题目】 一种特殊的链表节点类描述如下:
   public class Node { 
   		public int value; 
   		public Node next; 
   		public Node rand;
   		public Node(int data) { 
   			this.value = data; 
   		}
   }
 * Node类中的value是节点值,next指针和正常单链表中next指针的意义一 样,都指向下一个节点,
 * rand指针是Node类中新增的指针,这个指针可 能指向链表中的任意一个节点,也可能指向null。
 * 给定一个由Node节点类型组成的无环单链表的头节点head,请实现一个 函数完成这个链表中所有结构的复制,
 * 并返回复制的新链表的头节点。 
 * 进阶:不使用额外的数据结构,只用有限几个变量,且在时间复杂度为 O(N)内完成原问题要实现的函数。
 * @author Administrator
 *
 */
public class Code10_CopyListWithRandom {
	
	public static class Node {
		public int value;
		public Node next;
		public Node rand;
		
		public Node(int data) {
			this.value = data;
		}
	}
	
	// 使用哈希表
	public static Node copyListWithRand1(Node head) {
		Map<Node,Node> map = new HashMap<>();
		Node cur = head;
		while (cur != null) {
			map.put(cur, new Node(cur.value));
			cur = cur.next;
		}
		cur = head;
		while (cur != null) {
			map.get(cur).next = cur.next;
			map.get(cur).rand = cur.rand;
			cur = cur.next;
		}
		
		return map.get(head);
	}
	
	// 不使用哈希表
	public static Node copyListWithRand2(Node head) {
		if (head == null) {
			return null;
		}
		// copy node and link to every node 
		Node cur = head;
		Node next = null;
		while (cur != null) {
			next = cur.next;
			cur.next = new Node(cur.value);
			cur.next.next = next;
			cur = next;
		}
		// set copy node random
		cur = head;
		Node curCopy = null;
		while (cur != null) {
			next = cur.next.next;
			curCopy = cur.next;
			curCopy.rand = cur.rand != null ? cur.rand.next : null;
			cur = next;
		}
		// split
		Node res = head.next;
		cur = head;
		while (cur != null) {
			next = cur.next.next;
			curCopy = cur.next;
			curCopy.next = next !=null ? next.next : null;
			cur.next = next;
			cur = next;
		}
		
		return res;
	}
	
	public static void printRandLinkedList(Node head) {
		Node cur = head;
		System.out.print("order: ");
		while (cur != null) {
			System.out.print(cur.value + " ");
			cur = cur.next;
		}
		System.out.println();
		cur = head;
		System.out.print("rand:  ");
		while (cur != null) {
			System.out.print(cur.rand == null ? "- " : cur.rand.value + " ");
			cur = cur.next;
		}
		System.out.println();
	}

	public static void main(String[] args) {
		Node head = null;
		Node res1 = null;
		Node res2 = null;
		printRandLinkedList(head);
		res1 = copyListWithRand1(head);
		printRandLinkedList(res1);
		res2 = copyListWithRand2(head);
		printRandLinkedList(res2);
		printRandLinkedList(head);
		System.out.println("=========================");

		head = new Node(1);
		head.next = new Node(2);
		head.next.next = new Node(3);
		head.next.next.next = new Node(4);
		head.next.next.next.next = new Node(5);
		head.next.next.next.next.next = new Node(6);

		head.rand = head.next.next.next.next.next; // 1 -> 6
		head.next.rand = head.next.next.next.next.next; // 2 -> 6
		head.next.next.rand = head.next.next.next.next; // 3 -> 5
		head.next.next.next.rand = head.next.next; // 4 -> 3
		head.next.next.next.next.rand = null; // 5 -> null
		head.next.next.next.next.next.rand = head.next.next.next; // 6 -> 4

		printRandLinkedList(head);
		res1 = copyListWithRand1(head);
		printRandLinkedList(res1);
		res2 = copyListWithRand2(head);
		printRandLinkedList(res2);
		printRandLinkedList(head);
		System.out.println("=========================");

	}

}

测试结果

order: 
rand:  
order: 
rand:  
order: 
rand:  
order: 
rand:  
=========================
order: 1 2 3 4 5 6 
rand:  6 6 5 3 - 4 
order: 1 2 3 4 5 6 
rand:  6 6 5 3 - 4 
order: 1 2 3 4 5 6 
rand:  6 6 5 3 - 4 
order: 1 2 3 4 5 6 
rand:  6 6 5 3 - 4 
=========================

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值