我的算法学习笔记

目录

一.三种算法

1.选择排序、冒泡排序、插入排序(对数器验证)

二、二分查找

        1.查找特定值

        2.二分查找的应用(局部最小,时间复杂度logN)

三、异或运算的应用

四、链表、队列、栈

        a.反转链表

        b.用链表实现队列和栈

        c.用数组实现队列(常考题)(循环数组,用一个size巧妙解决问题)

        e.栈实现队列

        f.得到栈中最小值

五.哈希表的用法

六.归并排序实现和应用

1.递归和迭代实现归并排序

2.应用

a)小和问题(左边的数比右边小的数的和)

c)两倍大问题(num>右*2)


一.三种算法

1.选择排序、冒泡排序、插入排序(对数器验证)

package class1;

import java.util.Arrays;


public class SelectionSort {
	
	//选择排序
	public static void SelectionSort(int[] arr) {
		if(arr==null ||arr.length<2) {
			return;
		}
		for(int i=0;i<arr.length-1;i++)
		{
			int minindex=i;
			for(int j=i+1;j<arr.length;j++) {
				minindex=arr[j]<arr[minindex]?j:minindex;
			}
			swap(arr,minindex,i);
		}
		
	}
	
	//冒泡排序
	public static void bubuleSort(int[] arr) {
		if(arr==null ||arr.length<2) {
			return;
		}
		for(int e=arr.length-1;e>0;e--) {
			for(int i=0;i<e;i++) {
				if(arr[i]>arr[i+1]) {
					swap(arr,i,i+1);
				}
			}
		}
	}
	
	//插入排序
	public static void insertSort(int[] arr) {
		if(arr==null || arr.length<2) {
			return;
		}
		for(int i=1;i<arr.length;i++) {
			for(int j=i-1;j>=0 && arr[j]>arr[j+1];j--) {
				swap(arr,j,j+1);
			}
		}
	}
	
	
	public static void swap(int[] arr,int i,int j) {
		int t=arr[i];
		arr[i]=arr[j];
		arr[j]=t;
	}
	

	
	public static void comparator(int[] arr) {
		Arrays.sort(arr);
	}
	
	public static int[] generateRandomArray(int maxSize,int maxValue) {
		//Math.random()  -->[0,1);
		//Math.random()*N  -->[0,N);
		//(int)Math.random()*N  --->[0,N-1];
		int arr[]=new int[(int)((maxSize+1)*Math.random())];
		for(int i=0;i<arr.length;i++) {
			//产生[-N,N]的整数
			arr[i]=(int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
		}
		return arr;
		
	}

	
	public static int[] copyarray(int[] arr) {
		if(arr==null) {
			return null;
		}
		int[] res=new int[arr.length];
		for(int i=0;i<arr.length;i++) {
			res[i]=arr[i];
		}
		return res;
	}
	
	public static boolean isEqual(int[] arr,int[] res) {
		if((arr==null&&res!=null)||(arr!=null&&res==null) ) {
			return false;
		}
		if(arr.length!=res.length){
			return false;
		}
		if(arr==null&&res==null) {
			return true;
		}
		
		for(int i=0;i<arr.length;i++) {
			if(arr[i]!=res[i]) {
				return false;
			}
		}
		return true;
	}
	
	public static void printArray(int[] arr) {
		if(arr==null) {
			return;
		}
		for(int i=0;i<arr.length;i++) {
			System.out.print(arr[i]+" ");
		}
		System.out.println();
	}
	
	public static void main(String[] args) {
		int maxSize=100;
		int maxValue=100;
		int testtime=500000;
		boolean succeed=true;
		for(int i=0;i<testtime;i++) {
			int[] arr1=generateRandomArray(maxSize,maxValue);
			int[] arr2=copyarray(arr1);
			//bubuleSort(arr1);
			insertSort(arr1);
			comparator(arr2);
			if(!isEqual(arr1,arr2)) {
				succeed=false;
				printArray(arr1);
				printArray(arr2);
				
				break;
				
			}
		}
		System.out.println(succeed?"Nice!":"Fucking fucked!");
		int arr[]=generateRandomArray(maxSize,maxValue);
		printArray(arr);
		insertSort(arr);
		printArray(arr);
	}

}

二、二分查找

        1.查找特定值

package class1;

import java.util.Arrays;

public class BSExist {
	public static boolean exist (int[] sortArray,int num) {
		if(sortArray==null || sortArray.length==0) {
			return false;
		}
		int l=0;
		int r=sortArray.length-1;
		int mid=0;
		while(l<=r) {
			mid=l+((r-l)>>1);
			if(sortArray[mid]==num) {
				return true;
			}
			if(sortArray[mid]>num) {
				r=mid-1;
			}
			if(sortArray[mid]<num) {
				l=mid+1;
			}
		}
		//return sortArray[l] == num;这种情况是while的条件l<r
		return false;//这种情况是while的条件l<=r
		
	}
	
	public static boolean test(int[] sortArray,int num) {
		for(int cur:sortArray) {
			if(cur==num) {
				return true;
			}
		}
		return false;
	}
	
	public static void printArray(int[] arr) {
		if(arr==null) {
			return;
		}
		for(int i=0;i<arr.length;i++) {
			System.out.print(arr[i]+" ");
		}
		System.out.println();
	}
	
	public static int[] generateRandomArray(int maxSize, int maxValue) {
		int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
		}
		return arr;
	}
	
	public static void main(String[] args) {
		int maxSize=10;
		int maxValue=100;
		int testtime=500000;
		boolean succeed=true;
		for(int i=0;i<testtime;i++) {
			int arr[]=generateRandomArray(maxSize, maxValue);
			Arrays.sort(arr);
			int value = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
			if(exist(arr,value)!=test(arr,value)) {
				succeed=false;
				printArray(arr);
				System.out.println(value);
				break;
				
			}
			
		}
		System.out.println(succeed?"Nice!":"Fucking fucked!");
	}

}

        2.二分查找的应用(局部最小,时间复杂度logN)

public static int getLessindex(int[] arr) {
		if(arr==null || arr.length==0) {
			return -1;
		}
		if(arr.length==1 || arr[0]<arr[1]) {
			return 0;
		}
		if(arr[arr.length-2]>arr[arr.length-1]) {
			return arr.length-1;
		}
		
		int l=1;
		int r=arr.length-2;
		int mid=0;
		while(l<r) {
			mid=(l+r)>>1;
			if(arr[mid]>arr[mid-1]) {
				r=mid-1;
			}
			else if(arr[mid]>arr[mid+1]) {
				l=mid+1;
			}else {
				return mid;
			}
		}
		return l;
	}

三、异或运算的应用

        a.异或(无进位相加)

        0^N=N,  N^N=0;

        b.把int的最有的一位1取出来

        N&((~N)+1)   也可以等价于   N&(-N);

        c.去掉二进制中的一个1

        r=N&((~N)+1) 

        N^=r;

        d.应用(见代码)

package class1;

public class EvenTimesOddTimes {
	
	//一个数组中一个数出现奇数次,其余出现偶数次,找出那个出现奇数次的数
	public static void  printOddTimesNum1(int[] arr) {
		int eor=0;
		for(int i=0;i<arr.length;i++) {
			eor^=arr[i];
		}
		System.out.println(eor);
	}
	
	//一个数组中两个数出现奇数次,其余出现偶数次,找出那两个出现奇数次的数
	public static void  printOddTimesNum2(int[] arr) {
		int eor=0;
		for(int i=0;i<arr.length;i++) {
			eor^=arr[i];
		}
		int rightOne=eor&(-eor);
		int onlyOne=0;
		for(int i=0;i<arr.length;i++) {
			if((arr[i] & rightOne)!=0) {
				onlyOne^=arr[i];
			}
		}
		System.out.println(onlyOne+" "+(onlyOne^eor));
	}
	
	//数出一个二进制数中有多少个1
	public static int bit1counts(int n) {
		int count=0;
		int rightOne=0;
		while(n!=0) {
			rightOne=n&(-n);
			n^=rightOne;
			count++;
		}
		return count;
	}
	
	//使用异或交换两数
	public static void swap(int[] arr,int i,int j) {
		arr[i]=arr[i]^arr[j];
		arr[j]=arr[i]^arr[j];
		arr[i]=arr[i]^arr[j];
	}
	
	public static void main(String[] args) {
		int a=5;
		int b=7;
		
		System.out.println(a);
		System.out.println(b);
		
		a=a^b;
		b=a^b;
		a=a^b;
		
		System.out.println(a);
		System.out.println(b);
		
		int[] arr1 = { 3, 2, 3, 3, 1, 1, 1, 3, 1, 1, 1 };
		printOddTimesNum1(arr1);
		
		swap(arr1,0,1);
		System.out.println(arr1[0]+" "+arr1[1]);

		int[] arr2 = { 4, 3, 4, 2, 2, 2, 4, 1, 1, 1, 3, 3, 1, 1, 1, 4, 2, 2 };
		printOddTimesNum2(arr2);
	}

}

        异或运算的题目

package class1;

import java.util.HashMap;
import java.util.HashSet;

public class m_KM {
	
	//使用哈希表表,时间复杂度位O(N),空间复杂度位O(N)
	public static int test(int[] arr,int k,int m) {
		HashMap<Integer,Integer> map=new HashMap<>();
		for(int num:arr) {
			if(map.containsKey(num)) {
				map.put(num, map.get(num)+1);
				
			}else {
				map.put(num, 1);
			}
		}
		for(int num:map.keySet()) {
			if(map.get(num)==k) {
				return num;
			}
		}
		return -1;
	}
	
	public static HashMap<Integer,Integer> map=new HashMap<>();
	
	
	//使用位运算,时间复杂度位O(N),空间复杂度位O(N)
	public static int onlyKTimes(int[] arr,int k,int m) {
//		if(map.size()==0) {
//			mapCreater(map);
//		}
		int[] t=new int[32];
		for(int num:arr) {
			for(int i=0;i<32;i++) {
				//如果第i位为1,则t[i]++,记录位为1的个数
				t[i]+=(num>>i)&1;
			}
		}
		int ans=0;
		for(int i=0;i<32;i++) {
			
			//t[i]不能被整除,因为能被整除的一定不是k的数;
			if(t[i]%m!=0) {
				if(t[i]%m==k) {
					//那位为1就或上去
					ans |= (1<<i);
				}else {
					return -1;
				}
			}
		}
		//防止一个数出现3,其余出现7次,而0出现5次这种情况
		if(ans==0) {
			int count=0;
			for(int num:arr) {
				if(num==0) {
					count++;
				}
			}
			if(count!=k) {
				return -1;
			}
		}
		return ans;
	}
	
	public static void printArray(int[] arr) {
		if(arr==null) {
			return;
		}
		for(int i=0;i<arr.length;i++) {
			System.out.print(arr[i]+" ");
		}
		System.out.println();
	}
	
	public static int[] randomArray(int maxKinds, int range, int k, int m) {
		int ktimeNum=randomNumber(range);
		int times=Math.random()<0.5?k:((int) (Math.random() * (m - 1)) + 1);
		int numKinds=(int)(Math.random()*maxKinds)+2;
		int[] arr=new int [times+(numKinds-1)*m];
		int index=0;
		for(;index<times;index++) {
			arr[index]=ktimeNum;
		}
		
		numKinds--;
		//防止重复加数
		HashSet<Integer> set=new HashSet<>();
		set.add(ktimeNum);
		while(numKinds!=0) {
			int curNum=0;
			do {
				curNum=randomNumber(range);
			}while(set.contains(curNum));
			set.add(curNum);
			numKinds--;
			for(int i=0;i<m;i++) {
				arr[index++]=curNum;
			}
		}
		
		for(int i=0;i<arr.length;i++) {
			int j=(int)Math.random()*arr.length;
			int tmp=arr[i];
			arr[i]=arr[j];
			arr[j]=tmp;
		}
		return arr;
	}
	
	public static int randomNumber(int range) {
		return (int)(Math.random()*range+1)-(int)(Math.random()*range+1);
	}
	
	public static void main(String[] args) {
		int kinds = 5;
		int range = 30;
		int testTime = 100000;
		int max = 9;
		System.out.println("测试开始");
		for(int i=0;i<testTime;i++) {
			int a=(int)(Math.random()*max+1);
			int b=(int)(Math.random()*max+1);
			int k=Math.min(a, b);
			int m=Math.max(a, b);
			if(k==m) {
				m++;
			}
			int[] arr = randomArray(kinds, range, k, m);
			int ans1=test(arr,k,m);
			int ans2=onlyKTimes(arr,k,m);
			if(ans1!=ans2) {
				printArray(arr);
				System.out.println(ans1);
				System.out.println(ans2);
				System.out.println("出错了!");
				break;
			}
			
			
		}
		System.out.println("测试结束");
		
	}

}

四、链表、队列、栈

        a.反转链表

package class2;

import java.util.ArrayList;
import java.util.List;

public class list1 {

	public static class Node {
		public int value;
		public Node next;

		public Node(int data) {
			value = data;
		}
	}

	public static class DoubleNode {
		public int value;
		public DoubleNode last;
		public DoubleNode next;

		public DoubleNode(int data) {
			value = data;
		}
	}

	//  head
	//   a    ->   b    ->  c  ->  null
	//   c    ->   b    ->  a  ->  null
	public static Node reverseLinkedList(Node head) {
		Node pre = null;
		Node next = null;
		while (head != null) {
			next = head.next;
			head.next = pre;
			pre = head;
			head = next;
		}
		return pre;
	}

	public static DoubleNode reverseDoubleList(DoubleNode head) {
		DoubleNode pre = null;
		DoubleNode next = null;
		while (head != null) {
			next = head.next;
			head.next = pre;
			head.last = next;
			pre = head;
			head = next;
		}
		return pre;
	}

	public static Node testReverseLinkedList(Node head) {
		if (head == null) {
			return null;
		}
		ArrayList<Node> list = new ArrayList<>();
		while (head != null) {
			list.add(head);
			head = head.next;
		}
		list.get(0).next = null;
		int n = list.size();
		for (int i = 1; i < n; i++) {
			list.get(i).next = list.get(i - 1);
		}
		return list.get(n - 1);
	}

	public static DoubleNode testReverseDoubleList(DoubleNode head) {
		if (head == null) {
			return null;
		}
		ArrayList<DoubleNode> list = new ArrayList<>();
		while (head != null) {
			list.add(head);
			head = head.next;
		}
		list.get(0).next = null;
		DoubleNode pre = list.get(0);
		int N = list.size();
		for (int i = 1; i < N; i++) {
			DoubleNode cur = list.get(i);
			cur.last = null;
			cur.next = pre;
			pre.last = cur;
			pre = cur;
		}
		return list.get(N - 1);
	}

	// for test
	public static Node generateRandomLinkedList(int len, int value) {
		int size = (int) (Math.random() * (len + 1));
		if (size == 0) {
			return null;
		}
		size--;
		Node head = new Node((int) (Math.random() * (value + 1)));
		Node pre = head;
		while (size != 0) {
			Node cur = new Node((int) (Math.random() * (value + 1)));
			pre.next = cur;
			pre = cur;
			size--;
		}
		return head;
	}

	// for test
	public static DoubleNode generateRandomDoubleList(int len, int value) {
		int size = (int) (Math.random() * (len + 1));
		if (size == 0) {
			return null;
		}
		size--;
		DoubleNode head = new DoubleNode((int) (Math.random() * (value + 1)));
		DoubleNode pre = head;
		while (size != 0) {
			DoubleNode cur = new DoubleNode((int) (Math.random() * (value + 1)));
			pre.next = cur;
			cur.last = pre;
			pre = cur;
			size--;
		}
		return head;
	}

	// for test
	public static List<Integer> getLinkedListOriginOrder(Node head) {
		List<Integer> ans = new ArrayList<>();
		while (head != null) {
			ans.add(head.value);
			head = head.next;
		}
		return ans;
	}

	// for test
	public static boolean checkLinkedListReverse(List<Integer> origin, Node head) {
		for (int i = origin.size() - 1; i >= 0; i--) {
			if (!origin.get(i).equals(head.value)) {
				return false;
			}
			head = head.next;
		}
		return true;
	}

	// for test
	public static List<Integer> getDoubleListOriginOrder(DoubleNode head) {
		List<Integer> ans = new ArrayList<>();
		while (head != null) {
			ans.add(head.value);
			head = head.next;
		}
		return ans;
	}

	// for test
	public static boolean checkDoubleListReverse(List<Integer> origin, DoubleNode head) {
		DoubleNode end = null;
		for (int i = origin.size() - 1; i >= 0; i--) {
			if (!origin.get(i).equals(head.value)) {
				return false;
			}
			end = head;
			head = head.next;
		}
		for (int i = 0; i < origin.size(); i++) {
			if (!origin.get(i).equals(end.value)) {
				return false;
			}
			end = end.last;
		}
		return true;
	}

	// for test
	public static void main(String[] args) {
		int len = 50;
		int value = 100;
		int testTime = 100000;
		System.out.println("test begin!");
		for (int i = 0; i < testTime; i++) {
			Node node1 = generateRandomLinkedList(len, value);
			List<Integer> list1 = getLinkedListOriginOrder(node1);
			node1 = reverseLinkedList(node1);
			if (!checkLinkedListReverse(list1, node1)) {
				System.out.println("Oops1!");
			}

			Node node2 = generateRandomLinkedList(len, value);
			List<Integer> list2 = getLinkedListOriginOrder(node2);
			node2 = testReverseLinkedList(node2);
			if (!checkLinkedListReverse(list2, node2)) {
				System.out.println("Oops2!");
			}

			DoubleNode node3 = generateRandomDoubleList(len, value);
			List<Integer> list3 = getDoubleListOriginOrder(node3);
			node3 = reverseDoubleList(node3);
			if (!checkDoubleListReverse(list3, node3)) {
				System.out.println("Oops3!");
			}

			DoubleNode node4 = generateRandomDoubleList(len, value);
			List<Integer> list4 = getDoubleListOriginOrder(node4);
			node4 = reverseDoubleList(node4);
			if (!checkDoubleListReverse(list4, node4)) {
				System.out.println("Oops4!");
			}

		}
		System.out.println("test finish!");

	}

}

        b.用链表实现队列和栈

package class2;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;


public class doubleListapp {
	public static class Node<T>{
		public T value;
		public Node<T> last;
		public Node<T> next;
		
		public Node(T data) {
			value=data;
		}
	}
	
	public static class DoubleEndQueue<T>{
		Node<T> head;
		Node<T> tail;
		
		public void addFromHead(T value) {
			Node<T> cur=new Node<T>(value);
			if(head==null) {
				head=cur;
				tail=cur;
			}else {
				cur.next=head;
				head.last=cur;
				head=cur;
			}
		}
		
		public void addFromBottom(T value) {
			Node<T> cur=new Node<T>(value);
			if(head==null) {
				head=cur;
				tail=cur;
			}else {
				cur.last=tail;
				tail.next=cur;
				tail=cur;
			}
		}
		
		public T popFromHead() {
			if(head==null) {
				return null;
			}
			Node<T> cur=head;
			if(head==tail) {
				head=null;
				tail=null;
			}else {
				head=head.next;
				
				cur.next=null;
				head.last=null;
			}

			return cur.value;
		}
		
		public T popFromBottom() {
			if(head==null) {
				return null;
			}
			Node<T> cur=tail;
			if(head==tail) {
				tail=null;
				head=null;
			}else {
				tail=tail.last;
				tail.next=null;
				cur.last=null;
			}
			return cur.value;
		}
		
		public boolean isEmpty() {
			return head==null;
		}
	}
	
	public static class MyStack<T>{
		private DoubleEndQueue<T> queue;
		
		public MyStack() {
			queue=new DoubleEndQueue<T>();
		}
		public void push(T value) {
			queue.addFromBottom(value);
		}
		public T pop() {
			return queue.popFromBottom();
		}
		public boolean isEmpty()
		{
			return queue.isEmpty();
		}
	}
	
	public static class MyQueue<T>{
		private DoubleEndQueue<T> queue;
		
		public MyQueue(){
			queue=new DoubleEndQueue<T>();
			
		}
		public void push(T value) {
			queue.addFromBottom(value);
		}
		public T poll(){
			return queue.popFromHead();
		}
		
		public boolean isEmpty()
		{
			return queue.isEmpty();
		}
	}
	

	

	
	
	public static boolean isEqual(Integer o1, Integer o2) {
		if (o1 == null && o2 != null) {
			return false;
		}
		if (o1 != null && o2 == null) {
			return false;
		}
		if (o1 == null && o2 == null) {
			return true;
		}
		return o1.equals(o2);
	}

	public static void main(String[] args) {
		int oneTestDataNum = 100;
		int value = 10000;
		int testTimes = 100000;
		for (int i = 0; i < testTimes; i++) {
			MyStack<Integer> myStack = new MyStack<>();
			MyQueue<Integer> myQueue = new MyQueue<>();
			Stack<Integer> stack = new Stack<>();
			Queue<Integer> queue = new LinkedList<>();
			for (int j = 0; j < oneTestDataNum; j++) {
				int nums = (int) (Math.random() * value);
				if (stack.isEmpty()) {
					myStack.push(nums);
					stack.push(nums);
				} else {
					if (Math.random() < 0.5) {
						myStack.push(nums);
						stack.push(nums);
					} else {
						if (!isEqual(myStack.pop(), stack.pop())) {
							System.out.println("oops!");
						}
					}
				}
				int numq = (int) (Math.random() * value);
				if (stack.isEmpty()) {
					myQueue.push(numq);
					queue.offer(numq);
				} else {
					if (Math.random() < 0.5) {
						myQueue.push(numq);
						queue.offer(numq);
					} else {
						if (!isEqual(myQueue.poll(), queue.poll())) {
							System.out.println("oops!");
						}
					}
				}
			}
		}
		System.out.println("finish!");
	}


}

        c.用数组实现队列(常考题)(循环数组,用一个size巧妙解决问题)

package class2;

public class RingArray {

	public static class MyQueue{
		private int[] arr;
		private int pushi;
		private int polli;
		private int size;
		private final int limit;
		
		public MyQueue(int limit) {
			arr=new int[limit];
			pushi=0;
			polli=0;
			size=0;
			this.limit=limit;
		}
		
		public void push(int value) {
			if(size==limit) {
				throw new RuntimeException("队列满了,不能再加了");
			}
			size++;
			arr[pushi]=value;
			pushi=nextIndex(pushi);
			
		}
		
		public int pop() {
			if(size==0) {
				throw new RuntimeException("队列空了,不能再加了");
			}
			size--;
			int ans=arr[polli];
			polli=nextIndex(polli);
			return ans;
			
		}
		
		public boolean isEmpty() {
			return size==0;
		}
		
		private int nextIndex(int i) {
			return i<limit-1?i+1:0;
		}
	}
}

        d.队列实现栈

package class2;


import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class TwoQueueImplementStack {
	public static class TwoQueueStack<T>{
		public Queue<T> queue;
		public Queue<T> help;
		
		
		public TwoQueueStack() {
			queue = new LinkedList<>();
			help = new LinkedList<>();
		}
		
		public void push(T value) {
			queue.offer(value);
		}
		
		public T poll() {
			while(queue.size()>1) {
				help.offer(queue.poll());
			}
			T ans=queue.poll();
			Queue<T> tmp=queue;
			queue=help;
			help=tmp;
			return ans;
		}
		
		public T peek() {
			while(queue.size()>1) {
				help.offer(queue.poll());
			}
			T ans=queue.poll();
			help.offer(ans);
			Queue<T> tmp=queue;
			queue=help;
			help=tmp;
			return ans;
		}
		
		public boolean isEmpty() {
			return queue.isEmpty();
		}
	}
	
	public static void main(String[] args) {
		System.out.println("test begin!");
		TwoQueueStack<Integer> myStack=new TwoQueueStack<>();
		Stack<Integer> test=new Stack<>();
		int testTime=100000;
		int max=100000;
		for(int i=0;i<testTime;i++) {
			if(myStack.isEmpty()) {
				if(!test.isEmpty()) {
					System.out.println("Oops");
				}
				int num=(int)(Math.random()*max);
				myStack.push(num);
				test.push(num);
				
			}else {
				if(Math.random()<0.25) {
					int num=(int)(Math.random()*max);
					myStack.push(num);
					test.push(num);
				}else if(Math.random()<0.5) {
					if(!myStack.peek().equals(test.peek())) {
						System.out.println("Oops");
					}
				}else if(Math.random()<0.75) {
					if(!myStack.poll().equals(test.pop())) {
						System.out.println("Oops");
					}
				}else {
					if(myStack.isEmpty()!=test.isEmpty()) {
						System.out.println("Oops");
					}
				}
			}
		}
		System.out.println("test end!");
	}

	
		

}

        e.栈实现队列

package class2;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;

public class TQS {

	public static class TwoQueueStack<T> {
		public Queue<T> queue;
		public Queue<T> help;

		public TwoQueueStack() {
			queue = new LinkedList<>();
			help = new LinkedList<>();
		}

		public void push(T value) {
			queue.offer(value);
		}

		public T poll() {
			while (queue.size() > 1) {
				help.offer(queue.poll());
			}
			T ans = queue.poll();
			Queue<T> tmp = queue;
			queue = help;
			help = tmp;
			return ans;
		}

		public T peek() {
			while (queue.size() > 1) {
				help.offer(queue.poll());
			}
			T ans = queue.poll();
			help.offer(ans);
			Queue<T> tmp = queue;
			queue = help;
			help = tmp;
			return ans;
		}

		public boolean isEmpty() {
			return queue.isEmpty();
		}

	}

	public static void main(String[] args) {
		System.out.println("test begin");
		TwoQueueStack<Integer> myStack = new TwoQueueStack<>();
		Stack<Integer> test = new Stack<>();
		int testTime = 1000000;
		int max = 1000000;
		for (int i = 0; i < testTime; i++) {
			if (myStack.isEmpty()) {
				if (!test.isEmpty()) {
					System.out.println("Oops");
				}
				int num = (int) (Math.random() * max);
				myStack.push(num);
				test.push(num);
			} else {
				if (Math.random() < 0.25) {
					int num = (int) (Math.random() * max);
					myStack.push(num);
					test.push(num);
				} else if (Math.random() < 0.5) {
					if (!myStack.peek().equals(test.peek())) {
						System.out.println("Oops");
					}
				} else if (Math.random() < 0.75) {
					if (!myStack.poll().equals(test.pop())) {
						System.out.println("Oops");
					}
				} else {
					if (myStack.isEmpty() != test.isEmpty()) {
						System.out.println("Oops");
					}
				}
			}
		}

		System.out.println("test finish!");

	}

}

        f.得到栈中最小值

package class2;
import java.util.Stack;
public class GetMinStack {
	public static class Mystack1{
		public Stack<Integer> stackData;
		public Stack<Integer> stackMin;
		
		public Mystack1() {
			stackData=new Stack<>();
			stackMin=new Stack<>();
		}
		
		public void push(int newNum) {
			if(this.stackMin.isEmpty()) {
				stackMin.push(newNum);
			}else if(newNum<this.getmin()){
				stackMin.push(newNum);
			}
			stackData.push(newNum);
		}
		
		public int pop() {
			if(this.stackData.isEmpty()) {
				throw new RuntimeException("Your stack is empty");
			}
			int value=this.stackData.pop();
			if(value==this.getmin()) {
				this.stackMin.pop();
			}
			return value;
		}
		
		public int getmin() {
			if(this.stackMin.isEmpty()) {
				throw new RuntimeException("Your stack is empty");
			}
			return this.stackMin.peek();
		}
	}
	
	public static void main(String[] args) {
		Mystack1 stack1=new Mystack1();
		stack1.push(2);
		stack1.push(1);
		stack1.push(5);
		stack1.push(4);
		System.out.println(stack1.getmin());
		System.out.println(stack1.pop());
		System.out.println(stack1.pop());
		System.out.println(stack1.pop());
		System.out.println(stack1.getmin());
	}

}

五.哈希表的用法

package class2;

import java.util.HashMap;
import java.util.HashSet;
import java.util.TreeMap;

public class HM {

	public static class Node {
		public int value;

		public Node(int v) {
			value = v;
		}
	}

	public static class Zuo {
		public int value;

		public Zuo(int v) {
			value = v;
		}
	}

	public static void main(String[] args) {

		HashMap<Integer, String> test = new HashMap<>();
		Integer a = 19000000;
		Integer b = 19000000;
		System.out.println(a == b);

		test.put(a, "我是3");
		System.out.println(test.containsKey(b));

		Zuo z1 = new Zuo(1);
		Zuo z2 = new Zuo(1);
		HashMap<Zuo, String> test2 = new HashMap<>();
		test2.put(z1, "我是z1");
		System.out.println(test2.containsKey(z2));

		// UnSortedMap
		HashMap<Integer, String> map = new HashMap<>();
		map.put(1000000, "我是1000000");
		map.put(2, "我是2");
		map.put(3, "我是3");
		map.put(4, "我是4");
		map.put(5, "我是5");
		map.put(6, "我是6");
		map.put(1000000, "我是1000001");

		System.out.println(map.containsKey(1));
		System.out.println(map.containsKey(10));

		System.out.println(map.get(4));
		System.out.println(map.get(10));

		map.put(4, "他是4");
		System.out.println(map.get(4));

		map.remove(4);
		System.out.println(map.get(4));

		// key
		HashSet<String> set = new HashSet<>();
		set.add("abc");
		set.contains("abc");
		set.remove("abc");

		// 哈希表,增、删、改、查,在使用时,O(1)

		System.out.println("=====================");

		Integer c = 100000;
		Integer d = 100000;
		System.out.println(c.equals(d));

		Integer e = 127; // - 128 ~ 127
		Integer f = 127;
		System.out.println(e == f);

		HashMap<Node, String> map2 = new HashMap<>();
		Node node1 = new Node(1);
		Node node2 = node1;
		map2.put(node1, "我是node1");
		map2.put(node2, "我是node1");
		System.out.println(map2.size());

		System.out.println("======================");

		// TreeMap 有序表:接口名
		// 红黑树、avl、sb树、跳表
		// O(logN)
		System.out.println("有序表测试开始");
		TreeMap<Integer, String> treeMap = new TreeMap<>();

		treeMap.put(3, "我是3");
		treeMap.put(4, "我是4");
		treeMap.put(8, "我是8");
		treeMap.put(5, "我是5");
		treeMap.put(7, "我是7");
		treeMap.put(1, "我是1");
		treeMap.put(2, "我是2");

		System.out.println(treeMap.containsKey(1));
		System.out.println(treeMap.containsKey(10));

		System.out.println(treeMap.get(4));
		System.out.println(treeMap.get(10));

		treeMap.put(4, "他是4");
		System.out.println(treeMap.get(4));

		// treeMap.remove(4);
		System.out.println(treeMap.get(4));

		System.out.println("新鲜:");

		System.out.println(treeMap.firstKey());
		System.out.println(treeMap.lastKey());
		// <= 4
		System.out.println(treeMap.floorKey(4));
		// >= 4
		System.out.println(treeMap.ceilingKey(4));
		// O(logN)

	}

}

六.归并排序实现和应用

1.递归和迭代实现归并排序

package mergeSort;

public class MS {
	public static void mergeSort1(int[] arr) {
		if(arr==null || arr.length<2) {
			return;
		}
		process(arr,0,arr.length-1);
		
	}
	
	public static void process(int[] arr,int L,int R) {
		if(L==R) {
			return;
		}
		int M=L+((R-L)>>1);
		process(arr,L,M);
		process(arr,M+1,R);
		merge(arr,L,M,R);
	}
	
	public static void merge(int[] arr,int L,int M,int R) {
		int[] help=new int[R-L+1];
		int p1=L;
		int p2=M+1;
		int i=0;
		while(p1<=M && p2<=R) {
			help[i++]=arr[p1]<=arr[p2]?arr[p1++]:arr[p2++];
		}
		while(p1<=M) {
			help[i++]=arr[p1++];
		}
		while(p2<=R) {
			help[i++]=arr[p2++];
		}
		
		for(i=0;i<help.length;i++) {
			arr[i+L]=help[i];
		}
	}
	
	public static void mergeSort2(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}
		int N = arr.length;
		// 步长
		int mergeSize = 1;
		while (mergeSize < N) { // log N
			// 当前左组的,第一个位置
			int L = 0;
			while (L < N) {
				if (mergeSize >= N - L) {
					break;
				}
				int M = L + mergeSize - 1;
				int R = M + Math.min(mergeSize, N - M - 1);
				merge(arr, L, M, R);
				L = R + 1;
			}
			// 防止溢出
			if (mergeSize > N / 2) {
				break;
			}
			mergeSize <<= 1;
		}
	}

	// for test
	public static int[] generateRandomArray(int maxSize, int maxValue) {
		int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
		}
		return arr;
	}

	// for test
	public static int[] copyArray(int[] arr) {
		if (arr == null) {
			return null;
		}
		int[] res = new int[arr.length];
		for (int i = 0; i < arr.length; i++) {
			res[i] = arr[i];
		}
		return res;
	}

	// for test
	public static boolean isEqual(int[] arr1, int[] arr2) {
		if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
			return false;
		}
		if (arr1 == null && arr2 == null) {
			return true;
		}
		if (arr1.length != arr2.length) {
			return false;
		}
		for (int i = 0; i < arr1.length; i++) {
			if (arr1[i] != arr2[i]) {
				return false;
			}
		}
		return true;
	}

	// for test
	public static void printArray(int[] arr) {
		if (arr == null) {
			return;
		}
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
		System.out.println();
	}
	
	public static void main(String[] args) {
		int testTime = 500000;
		int maxSize = 100;
		int maxValue = 100;
		System.out.println("测试开始");
		for (int i = 0; i < testTime; i++) {
			int[] arr1 = generateRandomArray(maxSize, maxValue);
			int[] arr2 = copyArray(arr1);
			mergeSort1(arr1);
			mergeSort2(arr2);
			if (!isEqual(arr1, arr2)) {
				System.out.println("出错了!");
				printArray(arr1);
				printArray(arr2);
				break;
			}
		}
		System.out.println("测试结束");
	}

}

2.应用

a)小和问题(左边的数比右边小的数的和)

package mergeSort;

public class SmallSum {

	public static int smallSum(int[] arr) {
		if (arr == null || arr.length < 2) {
			return 0;
		}
		return process(arr, 0, arr.length - 1);
	}
	
	public static int process(int[] arr,int l,int r) {
		if(l==r) {
			return 0;
		}
		int m=l+((r-l)>>1);
		return process(arr,l,m)+process(arr,m+1,r)+merge(arr,l,m,r);
	}
	
	public static int merge(int[] arr,int l,int m,int r) {
		int[] help=new int[r-l+1];
		int i=0;
		int p1=l;
		int p2=m+1;
		int res=0;
		while(p1<=m && p2<=r) {
			res+=arr[p1]<arr[p2]?(r-p2+1)*arr[p1]:0;
			help[i++]=arr[p1]<arr[p2]?arr[p1++]:arr[p2++];
			
		}
		while(p1<=m) {
			help[i++]=arr[p1++];
		}
		while(p2<=r) {
			help[i++]=arr[p2++];
		}
		for(int j=0;j<help.length;j++) {
			arr[j+l]=help[j];
		}
		return res;
	}

	// arr[L..R]既要排好序,也要求小和返回
	// 所有merge时,产生的小和,累加
	// 左 排序   merge
	// 右 排序  merge
	// merge
//	public static int process(int[] arr, int l, int r) {
//		if (l == r) {
//			return 0;
//		}
//		// l < r
//		int mid = l + ((r - l) >> 1);
//		return 
//				process(arr, l, mid) 
//				+ 
//				process(arr, mid + 1, r) 
//				+ 
//				merge(arr, l, mid, r);
//	}
//
//	public static int merge(int[] arr, int L, int m, int r) {
//		int[] help = new int[r - L + 1];
//		int i = 0;
//		int p1 = L;
//		int p2 = m + 1;
//		int res = 0;
//		while (p1 <= m && p2 <= r) {
//			res += arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p1] : 0;
//			help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
//		}
//		while (p1 <= m) {
//			help[i++] = arr[p1++];
//		}
//		while (p2 <= r) {
//			help[i++] = arr[p2++];
//		}
//		for (i = 0; i < help.length; i++) {
//			arr[L + i] = help[i];
//		}
//		return res;
//	}

	// for test
//	public static int comparator(int[] arr) {
//		if (arr == null || arr.length < 2) {
//			return 0;
//		}
//		int res = 0;
//		for (int i = 1; i < arr.length; i++) {
//			for (int j = 0; j < i; j++) {
//				res += arr[j] < arr[i] ? arr[j] : 0;
//			}
//		}
//		return res;
//	}
	
	public static int comparator(int[] arr) {
		if(arr==null || arr.length<2) {
			return 0;
		}
		int sum=0;
		for(int i=1;i<arr.length;i++) {
			for(int j=0;j<i;j++) {
				sum+=arr[j]<arr[i]?arr[j]:0;
			}
		}
		return sum;
	}

	// for test
	public static int[] generateRandomArray(int maxSize, int maxValue) {
		int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
		}
		return arr;
	}

	// for test
	public static int[] copyArray(int[] arr) {
		if (arr == null) {
			return null;
		}
		int[] res = new int[arr.length];
		for (int i = 0; i < arr.length; i++) {
			res[i] = arr[i];
		}
		return res;
	}

	// for test
	public static boolean isEqual(int[] arr1, int[] arr2) {
		if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
			return false;
		}
		if (arr1 == null && arr2 == null) {
			return true;
		}
		if (arr1.length != arr2.length) {
			return false;
		}
		for (int i = 0; i < arr1.length; i++) {
			if (arr1[i] != arr2[i]) {
				return false;
			}
		}
		return true;
	}

	// for test
	public static void printArray(int[] arr) {
		if (arr == null) {
			return;
		}
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
		System.out.println();
	}

	// for test
	public static void main(String[] args) {
		int testTime = 500000;
		int maxSize = 100;
		int maxValue = 100;
		boolean succeed = true;
		for (int i = 0; i < testTime; i++) {
			int[] arr1 = generateRandomArray(maxSize, maxValue);
			int[] arr2 = copyArray(arr1);
			if (smallSum(arr1) != comparator(arr2)) {
				succeed = false;
				printArray(arr1);
				printArray(arr2);
				break;
			}
		}
		System.out.println(succeed ? "Nice!" : "Fucking fucked!");
	}

}

b)逆序对问题(求右比左小的个数)

package mergeSort;

public class reverseCouple {

	public static int smallSum(int[] arr) {
		if (arr == null || arr.length < 2) {
			return 0;
		}
		return process(arr, 0, arr.length - 1);
	}
	
	public static int process(int[] arr,int l,int r) {
		if(l==r) {
			return 0;
		}
		int m=l+((r-l)>>1);
		return process(arr,l,m)+process(arr,m+1,r)+merge(arr,l,m,r);
	}
	
	public static int merge(int[] arr,int l,int m,int r) {
		int[] help=new int[r-l+1];
		int i=help.length-1;
		int p1=m;
		int p2=r;
		int res=0;
		while(p1>=l && p2>m) {
			res+=arr[p1]>arr[p2]?(p2-m):0;
			help[i--]=arr[p1]>arr[p2]?arr[p1--]:arr[p2--];
			
		}
		while(p1>=l) {
			help[i--]=arr[p1--];
		}
		while(p2>m) {
			help[i--]=arr[p2--];
		}
		for(int j=0;j<help.length;j++) {
			arr[j+l]=help[j];
		}
		return res;
	}
	
	public static int comparator(int[] arr) {
		if(arr==null || arr.length<2) {
			return 0;
		}
		int sum=0;
		for(int i=0;i<arr.length;i++) {
			for(int j=i+1;j<arr.length;j++) {
				if(arr[i]>arr[j]) {
					sum++;
				}
			}
		}
		return sum;
	}

	// for test
	public static int[] generateRandomArray(int maxSize, int maxValue) {
		int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
		}
		return arr;
	}

	// for test
	public static int[] copyArray(int[] arr) {
		if (arr == null) {
			return null;
		}
		int[] res = new int[arr.length];
		for (int i = 0; i < arr.length; i++) {
			res[i] = arr[i];
		}
		return res;
	}

	// for test
	public static boolean isEqual(int[] arr1, int[] arr2) {
		if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
			return false;
		}
		if (arr1 == null && arr2 == null) {
			return true;
		}
		if (arr1.length != arr2.length) {
			return false;
		}
		for (int i = 0; i < arr1.length; i++) {
			if (arr1[i] != arr2[i]) {
				return false;
			}
		}
		return true;
	}

	// for test
	public static void printArray(int[] arr) {
		if (arr == null) {
			return;
		}
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
		System.out.println();
	}

	// for test
	public static void main(String[] args) {
		int testTime = 500000;
		int maxSize = 10;
		int maxValue = 100;
		boolean succeed = true;
//		int[] arr1 = generateRandomArray(maxSize, maxValue);
//		printArray(arr1);
//		int[] arr2 = copyArray(arr1);
//		printArray(arr2);
		for (int i = 0; i < testTime; i++) {
			int[] arr1 = generateRandomArray(maxSize, maxValue);
			int[] arr2 = copyArray(arr1);
			int a=smallSum(arr1);
			int b=comparator(arr2);
			if ( a!=b ) {
				
				printArray(arr1);
				printArray(arr2);
				succeed = false;
				System.out.println("a:"+a);
				System.out.println("b:"+b);
				
				break;
			}
		}
		System.out.println(succeed ? "Nice!" : "Fucking fucked!");
	}

}

c)两倍大问题(num>右*2)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 算法个人学习笔记pdf是一种以电子文档形式呈现的算法学习笔记资源。在这个pdf中,个人学习者可以记录和整理自己在学习算法过程中的思考、心得和解题方法。在这个学习笔记pdf中,个人学习者可以自由地添加和编辑自己的学习内容,包括算法的原理、算法实现的代码以及相应的思路和分析。通过这种方式,个人学习者可以更系统地学习和理解算法,并且能够随时查看自己的学习进展和学习成果。 通过编写和整理算法个人学习笔记pdf,个人学习者可以更好地理解和应用学习到的算法知识。这种记录和整理的过程可以帮助个人学习者更深入地思考问题和解决问题的方法,同时也可以帮助个人学习者更好地复习和回顾已学习算法知识。 对于其他学习者来说,算法个人学习笔记pdf也是一个宝贵的学习资源。其他学习者可以通过查阅个人学习者的学习笔记pdf,借鉴和学习其中的思路和方法。这样可以帮助其他学习者更好地理解和应用算法知识,同时也可以促进知识的分享和交流。 总的来说,算法个人学习笔记pdf是一个为个人学习者提供记录和整理学习过程的工具,同时也是一个为其他学习者提供学习资源和参考的媒介。通过编写和整理算法个人学习笔记pdf,个人学习者可以更好地学习和理解算法知识,同时也可以促进算法知识的分享和交流。 ### 回答2: 算法个人学习笔记pdf是一份记录个人学习算法的文档,具有以下特点和优势。 首先,这份学习笔记是以PDF格式保存的,这意味着可以在任何设备上方便地查看和阅读,无需依赖特定的平台或软件。无论是在电脑、平板还是手机上,都可以轻松地浏览和学习。 其次,这份学习笔记是个人整理的,因此具有个性化的特点。不同的人在学习算法时可能会关注和理解的重点有所不同,通过个人学习笔记,可以反映出个人对算法知识的理解和思考。这样的学习笔记对于个人的学习和复习过程非常有帮助。 此外,这份学习笔记应当具有清晰的结构和逻辑。算法知识通常是有层次结构的,基本的知识点和概念通常是必须掌握的基础,而进阶的知识则需要在掌握基础知识的基础上构建。学习笔记应当按照这个结构和逻辑进行组织,便于学习者理解和掌握。 最后,这份学习笔记应当具有实例和练习题。算法知识的学习不能仅仅停留在理论层面,还需要通过实际的例子和练习题进行实践和巩固。学习笔记应当包含这些实例和练习题,并给出相应的解析和答案,方便学习者进行练习和巩固。 总而言之,算法个人学习笔记pdf是一份方便、个性化、结构清晰、包含实例和练习题的文档,对于学习者来说非常有价值。 ### 回答3: 算法学习笔记PDF是一份用于记录个人学习算法的文档。通过编写学习笔记,我可以对算法的理论和实践有更深入的理解和掌握。 首先,在学习算法的过程中,理论与实践结合是非常重要的。在学习笔记中,我可以记录下算法的原理和相关的数学推导,以及对应的代码实现和应用场景。通过这样的记录方式,我可以更好地理解算法的本质和使用方式。 其次,学习笔记可以帮助我回顾和巩固所学的知识。通过整理和总结学习笔记,我可以梳理出算法的基础知识和重要思想,并将其记忆固定下来。同时,学习笔记也可以作为复习的资料,提供方便快捷的回顾方式。 此外,学习笔记还可以促进自我思考和学习方法的改进。在编写笔记的过程中,我可以思考和提出自己的问题,并通过查阅相关资料和与他人讨论,来找到问题的答案和解决方案。这样的思考过程可以帮助我提高问题解决的能力和学习效果。 最后,学习笔记可以与他人分享和交流。通过分享学习笔记,我可以与其他学习者进行交流和讨论,互相学习和提高。同时,学习笔记也可以作为自己学习和成长的见证,激励自己坚持学习和进步。 总之,算法个人学习笔记PDF是一份记录、回顾、思考和分享的文档,对于个人的算法学习具有重要的意义。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值