初级--03---二分、复杂度、哈希表和有序表

文章目录

  • 二分法
    • 题目1
      • 测试-----制造对数器
    • int mid = (L + R) / 2; 有可能int溢出
    • 优化为: ==int mid = L + ((R - L) >> 1);==
    • 题目2
  • 局部最小值问题
  • 时间复杂度
        • 基础--04----时间、空间复杂度
  • 哈希表
    • 哈希表可以看成一个(K V)表
        • ==哈希表的增删改查,时间复杂度都可以看成 O(1)==
    • 哈希表分类:
    • HashMap
        • 基础类型 : int double char string ------按值传递
        • 对象类型 : int double char string ------引用传递
  • 有序表
        • ==TreeMap的增删改查,时间复杂度都可以看成 O(n)==
    • java数据结构
    • TreeMap
    • TreeMap 的key 一定要能够比较,不然会报错


二分法

题目1

在这里插入图片描述

	// arr保证有序
	public static boolean find(int[] arr, int num) {
		if (arr == null || arr.length == 0) {
			return false;
		}
		int L = 0;
		int R = arr.length - 1;
		while (L <= R) {
			int mid = (L + R) / 2;
			if (arr[mid] == num) {
				return true;
			} else if (arr[mid] < num) {
				L = mid + 1;
			} else {
				R = mid - 1;
			}
		}
		return false;
	}

测试-----制造对数器

package main.java.newcode;

import java.util.Arrays;

public class Code01_BSExist {

    // arr保证有序
    public static boolean find(int[] arr, int num) {
        if (arr == null || arr.length == 0) {
            return false;
        }
        int L = 0;
        int R = arr.length - 1;
        while (L <= R) {
            int mid = (L + R) / 2;
            if (arr[mid] == num) {
                return true;
            } else if (arr[mid] < num) {
                L = mid + 1;
            } else {
                R = mid - 1;
            }
        }
        return false;

    }

    // for test
    public static boolean test(int[] sortedArr, int num) {
        for (int cur : sortedArr) {
            if (cur == num) {
                return true;
            }
        }
        return false;
    }

    // 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;
    }

    public static void main(String[] args) {
        int testTime = 500000;
        int maxSize = 10;
        int maxValue = 100;
        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 (test(arr, value) != find(arr, value)) {
                System.out.println("出错了!");
                succeed = false;
                break;
            }
        }
        System.out.println(succeed ? "Nice!" : "Fucking fucked!");
    }

}

初级--03---二分、复杂度、哈希表和有序表_第1张图片

int mid = (L + R) / 2; 有可能int溢出

优化为: int mid = L + ((R - L) >> 1);

 // arr保证有序
    public static boolean find(int[] arr, int num) {
        if (arr == null || arr.length == 0) {
            return false;
        }
        int L = 0;
        int R = arr.length - 1;
        while (L <= R) {
            int mid = L + ((R - L) >> 1);
            if (arr[mid] == num) {
                return true;
            } else if (arr[mid] < num) {
                L = mid + 1;
            } else {
                R = mid - 1;
            }
        }
        return false;

    }

题目2

在这里插入图片描述

	// arr有序的,>=num 最左
	public static int mostLeftNoLessNumIndex(int[] arr, int num) {
		if (arr == null || arr.length == 0) {
			return -1;
		}
		int L = 0;
		int R = arr.length - 1;
		int ans = -1;
		while (L <= R) {
			int mid = (L + R) / 2;
			if (arr[mid] >= num) {
				ans = mid;
				R = mid - 1;
			} else {
				L = mid + 1;
			}
		}
		return ans;
	}

在这里插入图片描述

// 在arr上,找满足<=value的最右位置
	public static int nearestIndex(int[] arr, int value) {
		int L = 0;
		int R = arr.length - 1;
		int index = -1; // 记录最右的对号
		while (L <= R) {
			int mid = L + ((R - L) >> 1);
			if (arr[mid] <= value) {
				index = mid;
				L = mid + 1;
			} else {
				R = mid - 1;
			}
		}
		return index;
	}

局部最小值问题

在这里插入图片描述

public class Code04_BSAwesome {

	// arr 整体无序
	// arr 相邻的数不相等!
	public static int oneMinIndex(int[] arr) {
		if (arr == null || arr.length == 0) {
			return -1;
		}
		int N = arr.length;
		if (N == 1) {
			return 0;
		}
		if (arr[0] < arr[1]) {
			return 0;
		}
		if (arr[N - 1] < arr[N - 2]) {
			return N - 1;
		}
		int L = 0;
		int R = N - 1;
		// L...R 肯定有局部最小
		while (L < R - 1) {
			int mid = (L + R) / 2;
			if (arr[mid] < arr[mid - 1] && arr[mid] < arr[mid + 1]) {
				return mid;
			} else {
				if (arr[mid] > arr[mid - 1]) {
					R = mid - 1;
				} else {
					L = mid + 1;
				}
			}
		}
		return arr[L] < arr[R] ? L : R;
	}

	// 生成随机数组,且相邻数不相等
	public static int[] randomArray(int maxLen, int maxValue) {
		int len = (int) (Math.random() * maxLen);
		int[] arr = new int[len];
		if (len > 0) {
			arr[0] = (int) (Math.random() * maxValue);
			for (int i = 1; i < len; i++) {
				do {
					arr[i] = (int) (Math.random() * maxValue);
				} while (arr[i] == arr[i - 1]);
			}
		}
		return arr;
	}

	// 也用于测试
	public static boolean check(int[] arr, int minIndex) {
		if (arr.length == 0) {
			return minIndex == -1;
		}
		int left = minIndex - 1;
		int right = minIndex + 1;
		boolean leftBigger = left >= 0 ? arr[left] > arr[minIndex] : true;
		boolean rightBigger = right < arr.length ? arr[right] > arr[minIndex] : true;
		return leftBigger && rightBigger;
	}

	public static void printArray(int[] arr) {
		for (int num : arr) {
			System.out.print(num + " ");
		}
		System.out.println();
	}

	public static void main(String[] args) {
		int maxLen = 100;
		int maxValue = 200;
		int testTime = 1000000;
		System.out.println("测试开始");
		for (int i = 0; i < testTime; i++) {
			int[] arr = randomArray(maxLen, maxValue);
			int ans = oneMinIndex(arr);
			if (!check(arr, ans)) {
				printArray(arr);
				System.out.println(ans);
				break;
			}
		}
		System.out.println("测试结束");

	}

}

时间复杂度

基础–04----时间、空间复杂度

哈希表

哈希表可以看成一个(K V)表

哈希表的增删改查,时间复杂度都可以看成 O(1)

哈希表分类:

  • 引用传递
  • 按值传递

HashMap

基础类型 : int double char string ------按值传递

    public static void main(String[] args) {

        HashMap<Integer, String> map2 = new HashMap<>();
        map2.put(1234567, "我是1234567");

        Integer a = 1234567;
        Integer b = 1234567;

        System.out.println(a == b);
        System.out.println(map2.containsKey(a));
        System.out.println(map2.containsKey(b));
        
   }

初级--03---二分、复杂度、哈希表和有序表_第2张图片

对象类型 : int double char string ------引用传递

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

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

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

    // (K V)表
    public static void main(String[] args) {

        Node node1 = new Node(1);
        Node node2 = new Node(1);
        HashMap<Node, String> map3 = new HashMap<>();
        map3.put(node1, "我进来了!");
        System.out.println(map3.containsKey(node1));
        System.out.println(map3.containsKey(node2));

    }

}

初级--03---二分、复杂度、哈希表和有序表_第3张图片

有序表

TreeMap的增删改查,时间复杂度都可以看成 O(n)

java数据结构

初级--03---二分、复杂度、哈希表和有序表_第4张图片
初级--03---二分、复杂度、哈希表和有序表_第5张图片

TreeMap

 public static void main(String[] args) {

        TreeMap<Integer, String> treeMap1 = new TreeMap<>();

        treeMap1.put(3, "我是3");
        treeMap1.put(0, "我是3");
        treeMap1.put(7, "我是3");
        treeMap1.put(2, "我是3");
        treeMap1.put(5, "我是3");
        treeMap1.put(9, "我是3");

        System.out.println(treeMap1.containsKey(7));
        System.out.println(treeMap1.containsKey(6));
        System.out.println(treeMap1.get(3));

        treeMap1.put(3, "他是3");
        System.out.println(treeMap1.get(3));

        treeMap1.remove(3);
        System.out.println(treeMap1.get(3));

        System.out.println(treeMap1.firstKey());
        System.out.println(treeMap1.lastKey());
        // <=5 离5最近的key告诉我
        System.out.println(treeMap1.floorKey(5));
        // <=6 离6最近的key告诉我
        System.out.println(treeMap1.floorKey(6));
        // >=5 离5最近的key告诉我
        System.out.println(treeMap1.ceilingKey(5));
        // >=6 离6最近的key告诉我
        System.out.println(treeMap1.ceilingKey(6));

//		Node node3 = new Node(3);
//		Node node4 = new Node(4);
//		TreeMap treeMap2 = new TreeMap<>();
//		treeMap2.put(node3, "我是node3");
//		treeMap2.put(node4, "我是node4");


    }

初级--03---二分、复杂度、哈希表和有序表_第6张图片

TreeMap 的key 一定要能够比较,不然会报错

import java.util.TreeMap;

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

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


    public static void main(String[] args) {

        TreeMap<Integer, String> treeMap1 = new TreeMap<>();

		Node node3 = new Node(3);
		Node node4 = new Node(4);
		TreeMap<Node, String> treeMap2 = new TreeMap<>();
		treeMap2.put(node3, "我是node3");
		treeMap2.put(node4, "我是node4");

    }

}

在这里插入图片描述

你可能感兴趣的:(算法03---左神算法,散列表,排序算法,算法)