Java程序员面试笔记_第八章_数据结构和算法_链表

package Java_Interview_Book;
import java.util.Hashtable;

class Node{
	Node next = null;
	int data;
	public Node(int data ) {
		this.data = data;
	}
}
public class LinkList_book {
	static Node head = null;
	/**
	 * 
	 * @return 返回结点长度
	 */
	public static int length() {
		int length = 0;
		Node tmp = head;
		while(tmp != null) {
			length++;
			tmp = tmp.next;
		}
		return length;
	}
	/* *
	 * @param d :插入的数据插到表尾
	 */
	public  void addNode(int d) {
		Node newNode = new Node(d);
		if(head == null) {
			head = newNode;
			return;
		}
		Node tmp = head;
		while(tmp.next != null) {
			tmp = tmp.next;
		}
		tmp.next = newNode;
	}
	/**
	 * 
	 * @param index:删除第index个结点
	 * @return 成功返回true,失败返回false
	 */
	public static boolean deleteNode(int index) {
		if(index < 1 || index > length()) {
			return false;
		}
		if(index == 1) {
			head = head.next;
			return true;
		}
		int i = 2;
		Node preNode = head;
		Node curNode = preNode.next;
		while(curNode != null ) {
			if(i == index) {
				preNode.next = curNode.next;
				return true;
			}
			preNode =curNode;
			curNode = curNode.next;
			i++;
		}
		return true;
	}
	/**
	 * 
	 * 对链表进行排序
	 * 输出排序后的头结点
	 */
	public Node orderList() {
		int temp = 0;
		Node curNode = head ; 
		Node nextNode = null;
		while(curNode != null) {
			nextNode = curNode.next;
			while(nextNode != null ) {
				if(curNode.data > nextNode.data) {
					temp = curNode.data;
					curNode.data  = nextNode.data;
					nextNode.data = temp;
				}
				nextNode =nextNode.next;
			}
			curNode = curNode.next;
		}
		return head;
	}
	public void printList() {
		Node tmp = head;
		while(tmp != null) {
			System.out.println(tmp.data);
			tmp = tmp.next;
		}
	}
	/**
	 * 从链表中删除重复数据,需要额外空间
	 * @param head 头结点
	 */
	public void deleteDuplecate1(Node head) {
		Hashtable< Integer, Integer> table = new Hashtable<Integer,Integer>();
		Node tmp = head;
		Node pre = null;
		while (tmp != null) {
			if (table.containsKey(tmp.data)) {
				pre.next = tmp.next;
			}else {
				table.put(tmp.data,1);
				pre = tmp ;
			}
			tmp = tmp.next;
		}
	}
	/**
	 * 不需要额外存储空间
	 * @param head
	 */
	public void deleteDuplecate2(Node head) {
		Node p = head;
		while (p != null) {
			Node q = p;
			while(q.next != null) {
				if (p.data == q.next.data) {
					q.next = q.next.next;
				}else {
					q = q.next;
				}
			}
			p = p.next;
		}
	}
	/**
	 * 找到单链表中倒数第k个元素
	 * @param head
	 * @param k
	 * @return 
	 */
	public Node findElem(Node head,int k) {
		if(k < 1) {
			return null;
		}
		Node p1 = head;
		Node p2 = head;
		for (int i = 0; i < k-1 && p1 != null; i++) {
			p1 = p1.next;
			if (p1 == null) {
				System.out.println("k不合法");
				return null;
			}
			while (p1.next != null) {
				p1 = p1.next;
				p2 = p2.next;				
			}
		}
		return p2;
	}
	/**
	 * 从尾到头输出单链表
	 * @param pListHead
	 */
	public void printListReversly(Node pListHead) {
		if(pListHead != null) {
			printListReversly(pListHead.next);
			System.out.println(pListHead.data);
		}
	}
	/**
	 * 寻找单链表中间结点
	 * @param head
	 * @return
	 */
	public static Node searchMiddleNode(Node head) {
		//使用快慢指针,快指针走两步,满指针走一步
		Node fastNode = head;
		Node slowNode = head;
		while(fastNode!=null && fastNode.next!=null && fastNode.next.next!=null) {
			fastNode = fastNode.next.next;
			slowNode = slowNode.next;
		}
		return slowNode;
	}
	/**
	 * 检测一个链表是否有环
	 * @param head
	 * @return
	 */
	public static boolean hasLoop(Node head) {
		//快慢指针,如果快慢指针相遇的话,则有,否则快指针到尾部的话,还没相遇则是无环
		Node fastNode = head;
		Node slowNode = head;
		if(fastNode == null) {
			return false;
		}
		while(fastNode != null && fastNode.next != null) {
			fastNode = fastNode.next.next;
			slowNode = slowNode.next;
			if(fastNode == slowNode) {
				return true;
			}
		}
		return !(fastNode == null || fastNode.next == null);
	}
	/**
	 * 找到环的入口
	 * @param head
	 * @return
	 * 设环长为r,满指针走了s步,快指针比满指针多走了n圈
	 * 2s=s+nr;
	 * 设整个链表长L,入口到相遇点距离为X,起点到换入口为a;
	 * a=(n-1)r+(L-a-x);
	 * 在链表头和,相遇点各设一个指针,每次走一步,则必定相遇
	 */
	public static Node FindLoopPort(Node head) {
		//快慢指针初始化
		Node fastNode = head;
		Node slowNode = head;
		while(fastNode != null && fastNode.next != null) {
			fastNode = fastNode.next.next;
			slowNode = slowNode.next;
			if(fastNode == slowNode) {
				break;
			}
		}
		//判断到结尾了,还没有环
		if(fastNode == null || fastNode.next == null) {
			return null;
		}
		slowNode = head;
		while(slowNode != fastNode) {
			fastNode = fastNode.next;
			slowNode = slowNode.next;
		}
		
		return slowNode;
	}
	/**
	 * 在不知道头指针情况下删除指定结点
	 * @param n
	 * @return
	 * 如果删除的是尾结点,无法删除,因为删除后无法使其前驱结点的next指针置为空;
	 * 不是尾结点,通过交换这个结点与其后继结点的值,然后删除后继结点。
	 */
	public static boolean deleteNode(Node n) {
		if(n == null || n.next == null) {
			return false;
		}
		//将n结点和n+1结点的值交换
		int temp = n.data;
		n.data=n.next.data;
		n.next.data =temp;
		//删除第n+1个结点
		n.next =n.next.next;		
		return true;
	}
	/**
	 * 判断两个链表是否相交
	 * @param h1
	 * @param h2
	 * @return
	 * 复杂度两个链表相加长度
	 */
	public static boolean isIntersect(Node h1,Node h2) {
		//如果两条链有一条为空,则不相交
		if(h1 == null || h2 == null) {
			return false;
		}
		//遍历两个链表,如果尾节点相同,两个链表肯定相交
		//找到两个链表尾节点
		Node tail1 = h1;
		while(tail1.next!=null) {
			tail1 = tail1.next;
		}
		Node tail2 = h2;
		while(tail2.next!=null) {
			tail2 = tail2.next;
		}
		return tail1 ==tail2;		
	}
	/**
	 * 找到两个相交链表的第一个节点
	 * @param h1
	 * @param h2
	 * @return
	 */
	public static Node getFirstMeetNode(Node h1,Node h2) {
		//如果两个链表相交的话,才去找节点
		//需要统计两个链表长度,让较长的链表指针先走(链表长度差),然后两个链表指针一起走
		//先判断是否相交
		//如果两条链有一条为空,则不相交
		if(h1 == null || h2 == null) {
			return null;
		}
		//遍历两个链表,如果尾节点相同,两个链表肯定相交
		//找到两个链表尾节点
		int length1=0;
		int length2=0;
		Node tail1 = h1;
		while(tail1.next!=null) {
			tail1 = tail1.next;
			length1++;
		}
		Node tail2 = h2;
		while(tail2.next!=null) {
			tail2 = tail2.next;
			length2++;
		}
		//不想交则返回空指针
		if(tail1 !=tail2) {
			return null;
		}
		//两个指针重新指向链表头,不想重新开辟新结点了,累
		tail1 =h1;
		tail2 =h2;
		if(length1>length2) {
			int difference = length1-length2;
			while(difference!=0) {
				tail1 =tail1.next;
				difference--;
			}
		}else {
			int difference = length2-length1;
			while(difference!=0) {
				tail2 =tail2.next;
				difference--;		
			}
		}
		//两个指针同时移动
		while(tail1 != tail2) {
			tail1 =tail1.next;
			tail2 =tail2.next;
		}
		return tail1;
	}
	public static void main(String[] args) {
		LinkList_book list = new LinkList_book();
//		System.out.println("----add----");
		list.addNode(5);
		list.addNode(1);
		list.addNode(2);
		list.addNode(3);
		list.addNode(2);		
//		list.printList();
//		System.out.println("Listlength:" + list.length());
//		System.out.println("---delete---");
//		list.deleteNode(2);
//		list.printList();
//		System.out.println("----order----");
//		System.out.println("Before");
//		list.printList();
//		System.out.println("After");
//		list.orderList();
//		list.printList();
//		System.out.println("----deleteDuplecate----");
//		Node head =list.head;
//		list.deleteDuplecate1(head);
//		list.deleteDuplecate2(head);
//		list.printList();
//		System.out.println("----findElemBackwardsNumberK----");
//		Node head =list.head;
//		int k = 2;
//		Node temp = list.findElem(head, k);
//		System.out.println(temp.data);
//		System.out.println("---- printListReversly----");
//		Node head =list.head;
//		list.printListReversly(head);
//		System.out.println("---- searchMiddleNode----");
//		Node head = list.head;
//		Node temp = list.searchMiddleNode(head);
//		System.out.println(temp.data);
//		System.out.println("---- hasLoop----");
//		Node head =list.head;
//		boolean  result =  list.hasLoop(head);
//		System.out.println(result);
//		System.out.println("---- hasLoop+FindLoopPort----");		
//		Node head1 = new Node(5);
//		Node node2 = new Node(3);
//		Node node3 = new Node(1);
//		Node node4 = new Node(2);
//		Node node5 = new Node(7);
//		Node tail1 = new Node(6);		
//		head1.next = node2;
//		node2.next = node3;
//		node3.next = node4;
//		node4.next = node5;
//		node5.next = tail1;
//		tail1.next = node3;
//		boolean  result = hasLoop(head1);
//		System.out.println(result);
//		Node temp = FindLoopPort(head1);
//		System.out.println(temp.data);
//		System.out.println("---- 在不知道头指针情况下删除指定结点----");
//		Node head1 = new Node(5);
//		Node node2 = new Node(3);
//		Node node3 = new Node(1);
//		Node node4 = new Node(2);
//		Node node5 = new Node(7);
//		Node tail1 = new Node(6);		
//		head1.next = node2;
//		node2.next = node3;
//		node3.next = node4;
//		node4.next = node5;
//		node5.next = tail1;
//		tail1.next = null;
//		boolean result = deleteNode(4);
//		System.out.println(result);
//		Node temp = head1;
//		while (temp.next!=null) {
//			System.out.println(temp.data);
//			temp = temp.next;
//		}
//		System.out.println("---- isIntersect----");
//		Node head1 = new Node(5);
//		Node node2 = new Node(3);
//		Node node3 = new Node(1);
//		Node node4 = new Node(2);
//		Node node5 = new Node(7);
//		Node tail1 = new Node(6);		
//		head1.next = node2;
//		node2.next = node3;
//		node3.next = node4;
//		node4.next = node5;
//		node5.next = tail1;
//		tail1.next = null;
//		Node head = list.head;
//		boolean result1 = isIntersect(head, head1);
//		System.out.println(result1);
//		Node head11 = new Node(7);
//		Node node21 = new Node(2);
//		Node node31 = new Node(1);		
//		head11.next = node21;
//		node21.next = node31;
//		node31.next = node4;
//		boolean result2 = isIntersect(head11, head1);
//		System.out.println(result2);		
//		System.out.println("---- getFirstMeetNode----");
//		Node temp = getFirstMeetNode(head11, head1);
//		System.out.println(temp.data);
	}
}

猜你喜欢

转载自blog.csdn.net/hxl0925/article/details/89414475