10.3lc
今天又是躺平的一天 。
国庆真是个结婚的好日子~~~ 我爸同事天天婚宴…
写了每日易题: 和几道排序 简单的回归一个 八大排序:
个人感觉:其实 主要的 插入 堆 快排 基数 希尔。
快排的复杂度:和分区点 有着很大的关系 建议最好还是 随计选择
先回顾一哈排序
a八大排序
1.冒泡排序
思想:依次进行比较,选择最大的从后往前排,知道比较 arr.length-1次;
public static void bublerSorted(int[] arr){
//领时交换变量;
int temp=0;
int length=arr.length;
for(int i=0;i<leng-1;i++){
//j<leng-1-i:每次循环比较后的 确定i位,所以会-i 比较剩下的位置的元素
for(int j=0;j<leng-1-i;j++){
if(arr[j]>arr[j+1]){
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
System.out.println(Arrays.toString(arr));
}
}
2.选择排序
思想:选择一个最小的:从前往后排:类似于 先排小 后排大:存的是索引的 所以速度比冒泡快一点:
因为在 内部的一次for循环中 数组存储的只是最小值和最小值的索引 所以少存一个值 快
public static void chooseSorted(int[] arr){
for(int i=0;i<arr.length-1;i++){
int minIndex=i;
int min=arr[i];
for(int j=i+1;j<arr.length-1,j++){
if(min >arr[j]){
min=arr[j];
minIndex=j;
}
if(minIndex !=0){
arr[minIndex]=arr[i];
arr[i]=min;
}
}
}
System.out.println(Arrays.toString(arr));
}
3.插入排序:
思想:每次都是最后一个数字 进行插入 其实位置 为 i-1; 类似起牌!
public static void insertSotred(int[] arr){
int insertVal=0;
int inserIndex=0;
for(int i=0;i<arr.length-1;i++){
insertVal=arr[i+1];
inserIndex=i;
while(insertIndex >= 0 &&arr[insertIndex]> insertVal){
arr[insertIndex+1]=arr[insertIndex];
insertIndex--;
}
arr[insertIndex+1] = insertVal;
}
System.out.println(Arrays.toString(arr));
}
public static void insertSotred(int[] arr){
for(int i=0;i<arr.length-1;i++){
for(int j=i-1;j>0&&arr[j]>arr[j+1];j--;)
int temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
System.out.println(Arrays.toString(arr));
}
4.希尔排序(交换)
思想:对于 插入排序的优化: 分组化进行 交换
public static void shellSorted(int[] arr){
int temp=0;
//临时中间变量
for(int gap = arr.length/2;gap >= 0;gap /=2){
//i<arr.lenth;要保证最后一位也能吃住:
for(int i=gap;i<arr.lenth;i++){
for(int j=i-gap; j>=0; j-=gap){
if(arr[j] > arr[j+gap]){
temp=arr[j];
arr[j]=arr[j+gap];
arr[j+gap]=temp;
}
}
}
}
}
5.希尔排序(插排)快
思想:把原来基于交换的思想 转换位 插入!
public static void shellSorted(int[] arr){
int temp=0;
//临时中间变量
for(int gap = arr.length/2;gap >= 0;gap /=2){
//i<arr.lenth;要保证最后一位也能吃住:
for(int i=gap;i<arr.lenth;i++){
int j=i;
int temp=arr[j]
while( j-gap >=0 && arr[j] < arr[j-gap]){
arr[j]=arr[j-gap];
j -=gap;
}
arr[j]=temp;
}
}
}
}
6.快速排序(重要)
: 顺序关系很重要!
从左边开始 就一定要从右边开始遍历 不然少一次遍历:
private static void quickSort(int[] arr, int left, int right) {
if (left < right) {
int partitionIndex = partition(arr, left, right);
quickSort(arr, left, partitionIndex - 1);
quickSort(arr, partitionIndex + 1, right);
}
}
private static int partition(int[] arr, int left, int right) {
int pivot = arr[left];
//终止while循环以后left和right一定相等的
while (left < right) {
while (left < right && arr[right] >= pivot) {
--right;
}
arr[left] = arr[right];
while (left < right && arr[left] <= pivot) {
++left;
}
arr[right] = arr[left];
}
arr[left] = pivot;
//right可以改为left
return left;
}
第二种
ublic static viod sort(int[] arr,int left,int right){
if(left>right){
return;
}
int baseNumber=arr[left];
int temp=0;
//中间变量
int l=left,r=right;
while(l != r){
while(arr[r]>=baseNumber && l < r){
r--;
}
while(arr[l]<=baseNumber && l < r){
l++;
}
if(l < r){
temp = arr[l];
arr[l] = arr[r];
arr[r] = temp;
}
//准基数归位
arr[left] = arr[l];
arr[l] = baseNumber;
sort(arr,left,l-1);
sort(arr,l+1,right);
}
}
public static void quickSort(int[] arr){ int len = arr.length; if(len ==null ||len == 1 ||len == 0){ return; } sort(arr,0,len-1);}public static void sort(int[] arr,int left, int right){ int base= arr[left]; int l=left,r=right; int temp=0; if(left > right){ return; } while(l != r ){ while(l<r && arr[r] >= base){ r--; } while(l<r && arr[l] <=base){ l++; } if(l<r){ temp=arr[l]; arr[l]=arr[r]; arr[r] =temp; } arr[left]=arr[l]; arr[l]=base; sort(arr,left,l-1); sort(arr,l+1,right); }}
7.基数排序
思想:分而治之
拆成最小快,排序后在进行合并
public static mergeSort(int[] arr,int left,int right,int[] temp){ int mid=(leth+right)/2; int[] temp=new int[arr.length]; mergeSort(arr,left,mid,temp); mergeSort(arr,mid+1,right,temp); sort(arr,)}
三大查找
1.线性查找
思想:就是直接遍历搜索:
public static int search(int[] arr, int findValue){ for(int i=0;i<arr.length-1;i++){ if(arr[i] == finfValue){ return i; } return -1; }}
2.二分查找:
思想:中间查找:注意一个数字问题
//注意:使用二分查找的前提是 该数组是有序的.public class BinarySearch { public static void main(String[] args) { int arr[] = { 1, 8, 10, 89, 1000, 1000, 1000, 1234 }; List<Integer> resIndexList = binarySearch(arr, 0, arr.length - 1, 1000); System.out.println("resIndexList=" + resIndexList); } // 完成一个课后思考题: /* * 课后思考题: {1,8, 10, 89, 1000, 1000,1234} 当一个有序数组中, 有多个相同的数值时,如何将所有的数值都查找到,比如这里的 * 1000 * * 思路分析 1. 在找到mid 索引值,不要马上返回 2. 向mid 索引值的左边扫描,将所有满足 1000, 的元素的下标,加入到集合ArrayList * 3. 向mid 索引值的右边扫描,将所有满足 1000, 的元素的下标,加入到集合ArrayList 4. 将Arraylist返回 */ public static List<Integer> binarySearch(int[] arr, int left, int right, int findVal) { // 当 left > right 时,说明递归整个数组,但是没有找到 if (left > right) { return new ArrayList<Integer>(); } int mid = (left + right) / 2; int midVal = arr[mid]; if (findVal > midVal) { // 向 右递归 return binarySearch(arr, mid + 1, right, findVal); } else if (findVal < midVal) { // 向左递归 return binarySearch(arr, left, mid - 1, findVal); } else { // 思路分析 // 1. 在找到mid 索引值,不要马上返回 // 2. 向mid 索引值的左边扫描,将所有满足 1000, 的元素的下标,加入到集合ArrayList // 3. 向mid 索引值的右边扫描,将所有满足 1000, 的元素的下标,加入到集合ArrayList // 4. 将Arraylist返回 List<Integer> resIndexlist = new ArrayList<Integer>(); // 向mid 索引值的左边扫描,将所有满足 1000, 的元素的下标,加入到集合ArrayList int temp = mid - 1; while (true) { if (temp < 0 || arr[temp] != findVal) {// 退出 break; } // 否则,就temp 放入到 resIndexlist resIndexlist.add(temp); temp -= 1; // temp左移 } resIndexlist.add(mid); // // 向mid 索引值的右边扫描,将所有满足 1000, 的元素的下标,加入到集合ArrayList temp = mid + 1; while (true) { if (temp > arr.length - 1 || arr[temp] != findVal) {// 退出 break; } // 否则,就temp 放入到 resIndexlist resIndexlist.add(temp); temp += 1; // temp右移 } return resIndexlist; } }}
3.插值查找
思想:就是换了的mid的公式 来进行 查找:
int mid = low + (high - low) * (key - arr[low]) / (arr[high] - arr[low]) ;
public static int insertFind(int[] arr,int left,int right,int findValue){ int mid=left+(right-left)*(findValue-arr[left])/(arr[right]-arr[left]); int midVal = arr[mid]; if (findVal > midVal) { // 说明应该向右边递归 return insertValueSearch(arr, mid + 1, right, findVal); } else if (findVal < midVal) { // 说明向左递归查找 return insertValueSearch(arr, left, mid - 1, findVal); } else { return mid; }}
166. 分数到小数 - 力扣(LeetCode) (leetcode-cn.com)
:直接思路运算即可
class Solution {
public String fractionToDecimal(int numerator, int denominator) {
long a =numerator,b=denominator;
if(a%b == 0) return String.valueOf(a/b);
StringBuilder sb=new StringBuilder();
// 判断符号 如果小 就是 一正一副 除为-
if(a*b<0) sb.append('-');
//转为正数
a=Math.abs(a); b=Math.abs(b);
//拼接 小数点 前
sb.append(String.valueOf(a/b)+'.');
// 余数
a%=b;
Map<Long,Integer> map=new HashMap<>();
while(a !=0){
// map 存的是 key 循环值 value : 长度
map.put(a,sb.length());
a*=10;
sb.append(a/b);
a%=b;
if(map.containsKey(a)){
int u =map.get(a);
//正则表达式的
return String.format("%s(%s)",sb.substring(0,u),sb.substring(u));
}
}
return sb.toString();
}
}
628. 三个数的最大乘积 - 力扣(LeetCode) (leetcode-cn.com)
:直接Arrays.sort()~~~
:或者 线性扫描
class Solution {
public int maximumProduct(int[] nums) {
int min1 = Integer.MAX_VALUE, min2 = Integer.MAX_VALUE;
// 最大的、第二大的和第三大的
int max1 = Integer.MIN_VALUE, max2 = Integer.MIN_VALUE, max3 = Integer.MIN_VALUE;
for(int x:nums){
if(x<min1){
min2=min1;
min1=x;
}else if(x<min2){
min2=x;
}
if(x>max1){
max3=max2;
max2=max1;
max1=x;
}else if (x>max2){
max3=max2;
max2=x;
}else if(x>max3){
max3=x;
}
}
return Math.max((max1*max2*max3),(min1*min2*max1));
}
}
88. 合并两个有序数组 - 力扣(LeetCode) (leetcode-cn.com)
:直接拼接
:或者 辅助数组 +双指针
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int i = m,j = 0;
while(i < m + n){
nums1[i++] = nums2[j++];
}
Arrays.sort(nums1);
}}