4.4 贪心 排序
This commit is contained in:
parent
03761c6e10
commit
d28142efa1
34
src/main/java/greedy/FindContentChildren.java
Normal file
34
src/main/java/greedy/FindContentChildren.java
Normal file
@ -0,0 +1,34 @@
|
||||
package greedy;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 题目: 455. 分发饼干 (maxProfit)
|
||||
* 描述:给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
|
||||
* 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
|
||||
* 返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
|
||||
|
||||
* 示例 1:
|
||||
输入: g = [1,2,3], s = [1,1]
|
||||
输出: 1
|
||||
解释:你有三个孩子和两块小饼干,3 个孩子的胃口值分别是:1,2,3。
|
||||
虽然你有两块小饼干,由于他们的尺寸都是 1,你只能让胃口值是 1 的孩子满足。
|
||||
所以你应该输出 1。
|
||||
|
||||
* 链接:https://leetcode.cn/problems/assign-cookies/
|
||||
*/
|
||||
public class FindContentChildren {
|
||||
public int findContentChildren(int[] g, int[] s) {
|
||||
int i=0,j=0,cnt=0;
|
||||
Arrays.sort(g);
|
||||
Arrays.sort(s);
|
||||
while (i<g.length&&j<s.length){
|
||||
if(g[i]<=s[j]) {
|
||||
cnt++;
|
||||
i++;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
}
|
36
src/main/java/greedy/MaxProfit.java
Normal file
36
src/main/java/greedy/MaxProfit.java
Normal file
@ -0,0 +1,36 @@
|
||||
package greedy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 题目: 121. 买卖股票的最佳时机 (maxProfit)
|
||||
* 描述:给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
|
||||
* 你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
|
||||
* 返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。
|
||||
|
||||
* 示例 1:
|
||||
输入:[7,1,5,3,6,4]
|
||||
输出:5
|
||||
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
|
||||
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
|
||||
|
||||
* 链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/
|
||||
*/
|
||||
//第一道贪心,学思路
|
||||
//每次都假设是今天卖出,然后求今天之前的历史最低点。
|
||||
public class MaxProfit {
|
||||
public int maxProfit(int prices[]) {
|
||||
int minprice = Integer.MAX_VALUE;
|
||||
int maxprofit = 0;
|
||||
for (int price : prices) {
|
||||
if (price < minprice) {
|
||||
minprice = price;
|
||||
} else if (price - minprice > maxprofit) {
|
||||
maxprofit = price - minprice;
|
||||
}
|
||||
}
|
||||
return maxprofit;
|
||||
}
|
||||
}
|
45
src/main/java/greedy/WiggleMaxLength.java
Normal file
45
src/main/java/greedy/WiggleMaxLength.java
Normal file
@ -0,0 +1,45 @@
|
||||
package greedy;
|
||||
/**
|
||||
* 题目: 376. 摆动序列 (wiggleMaxLength)
|
||||
* 描述:如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。
|
||||
* 例如, [1, 7, 4, 9, 2, 5] 是一个 摆动序列 ,因为差值 (6, -3, 5, -7, 3) 是正负交替出现的。
|
||||
* 相反,[1, 4, 7, 2, 5] 和 [1, 7, 4, 5, 5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。
|
||||
* 子序列 可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。
|
||||
* 给你一个整数数组 nums ,返回 nums 中作为 摆动序列 的 最长子序列的长度 。
|
||||
|
||||
* 示例 1:
|
||||
输入:nums = [1,7,4,9,2,5]
|
||||
输出:6
|
||||
解释:整个序列均为摆动序列,各元素之间的差值为 (6, -3, 5, -7, 3) 。
|
||||
|
||||
示例 2:
|
||||
输入:nums = [1,17,5,10,13,15,10,5,16,8]
|
||||
输出:7
|
||||
解释:这个序列包含几个长度为 7 摆动序列。
|
||||
其中一个是 [1, 17, 10, 13, 10, 16, 8] ,各元素之间的差值为 (16, -7, 3, -3, 6, -8) 。
|
||||
* 链接:https://leetcode.cn/problems/wiggle-subsequence/
|
||||
*/
|
||||
//不会 https://programmercarl.com/0376.%E6%91%86%E5%8A%A8%E5%BA%8F%E5%88%97.html
|
||||
public class WiggleMaxLength {
|
||||
public int wiggleMaxLength(int[] nums) {
|
||||
if (nums.length <= 1) {
|
||||
return nums.length;
|
||||
}
|
||||
//当前差值
|
||||
int curDiff = 0;
|
||||
//上一个差值
|
||||
int preDiff = 0;
|
||||
int count = 1;
|
||||
for (int i = 1; i < nums.length; i++) {
|
||||
//得到当前差值
|
||||
curDiff = nums[i] - nums[i - 1];
|
||||
//如果当前差值和上一个差值为一正一负
|
||||
//等于0的情况表示初始时的preDiff
|
||||
if ((curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0)) {
|
||||
count++;
|
||||
preDiff = curDiff;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
@ -4,11 +4,11 @@ import java.util.Comparator;
|
||||
import java.util.PriorityQueue;
|
||||
|
||||
/**
|
||||
* 题目: 215. 数组中的第K个最大元素 (floodFill)
|
||||
* 题目: 215. 数组中的第K个最大元素 (findKthLargest)
|
||||
* 描述:给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。
|
||||
* 请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
|
||||
* 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。
|
||||
|
||||
*
|
||||
* 示例 1:
|
||||
输入: [3,2,1,5,6,4], k = 2
|
||||
输出: 5
|
||||
@ -28,7 +28,7 @@ public class FindKthLargest {
|
||||
return maxheap.peek();
|
||||
}
|
||||
//使用最小堆来存储前 k 个最大的元素。堆顶元素是 k 个最大元素中的最小值。这样,堆的大小始终保持为 k。当堆的大小大于 k 时,弹出堆顶元素。最终堆顶元素就是第 k 大的元素。不需要完全填满堆再删除元素:
|
||||
public int findKthLargest(int[] nums, int k) {
|
||||
public int findKthLargest2(int[] nums, int k) {
|
||||
// 使用最小堆
|
||||
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
|
||||
|
||||
@ -47,4 +47,43 @@ public class FindKthLargest {
|
||||
// 返回堆顶元素,即为第 k 大的元素
|
||||
return minHeap.peek();
|
||||
}
|
||||
//快速选择
|
||||
public int quickselect(int[] nums, int l, int r, int k) {
|
||||
// 当区间内只有一个元素时,直接返回该元素
|
||||
if (l >= r) {
|
||||
return nums[l];
|
||||
}
|
||||
// 选取区间第一个元素作为枢轴
|
||||
int pivot = nums[l];
|
||||
int i = l, j = r;
|
||||
|
||||
// 分区过程:调整数组,使得左侧的元素不大于枢轴,右侧的元素不小于枢轴
|
||||
while (i < j) {
|
||||
// 从右边向左扫描,找到第一个小于 pivot 的元素,放到左侧
|
||||
while (i < j && nums[j] >= pivot) {
|
||||
j--;
|
||||
}
|
||||
nums[i] = nums[j];
|
||||
// 从左边向右扫描,找到第一个大于 pivot 的元素,放到右侧
|
||||
while (i < j && nums[i] <= pivot) {
|
||||
i++;
|
||||
}
|
||||
nums[j] = nums[i];
|
||||
}
|
||||
// 将枢轴放入正确的位置
|
||||
nums[i] = pivot;
|
||||
|
||||
// 现在 i 即为枢轴位置
|
||||
if (i == k) {
|
||||
return nums[i];
|
||||
} else if (k < i) {
|
||||
return quickselect(nums, l, i - 1, k);
|
||||
} else {
|
||||
return quickselect(nums, i + 1, r, k);
|
||||
}
|
||||
}
|
||||
public int findKthLargest(int[] _nums, int k) {
|
||||
int n = _nums.length;
|
||||
return quickselect(_nums, 0, n - 1, n - k);
|
||||
}
|
||||
}
|
||||
|
40
src/main/java/heap/TopKFrequent.java
Normal file
40
src/main/java/heap/TopKFrequent.java
Normal file
@ -0,0 +1,40 @@
|
||||
package heap;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.PriorityQueue;
|
||||
|
||||
/**
|
||||
* 题目: 347. 前 K 个高频元素 (topKFrequent)
|
||||
* 描述:给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
|
||||
|
||||
* 示例 1:
|
||||
输入: nums = [1,1,1,2,2,3], k = 2
|
||||
输出: [1,2]
|
||||
|
||||
* 链接:https://leetcode.cn/problems/top-k-frequent-elements/
|
||||
*/
|
||||
public class TopKFrequent {
|
||||
public int[] topKFrequent(int[] nums, int k) {
|
||||
HashMap<Integer,Integer>map=new HashMap<>();
|
||||
PriorityQueue<int[]> minHeap = new PriorityQueue<>(
|
||||
(a, b) -> b[1] - a[1]);
|
||||
int[] res=new int[k];
|
||||
int i=0;
|
||||
for (int num : nums) {
|
||||
if(!map.containsKey(num))
|
||||
map.put(num,1);
|
||||
else
|
||||
map.put(num,map.get(num)+1);
|
||||
}
|
||||
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
|
||||
minHeap.add(new int[]{entry.getKey(),entry.getValue()});
|
||||
}
|
||||
while (!minHeap.isEmpty()) {
|
||||
if(i<k)
|
||||
res[i++] = minHeap.poll()[0];
|
||||
else break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
26
src/main/java/sort/BubbleSort.java
Normal file
26
src/main/java/sort/BubbleSort.java
Normal file
@ -0,0 +1,26 @@
|
||||
package sort;
|
||||
|
||||
public class BubbleSort {
|
||||
public void bubbleSort(int[] arr){
|
||||
//n-1 趟冒泡
|
||||
for (int i = 0; i < arr.length-1; i++) {
|
||||
boolean flag=false;
|
||||
//冒泡
|
||||
for (int j = arr.length-1; j >i ; j--) {
|
||||
if (arr[j-1]>arr[j]){
|
||||
swap(arr,j-1,j);
|
||||
flag=true;
|
||||
}
|
||||
}
|
||||
//本趟遍历后没有发生交换,说明表已经有序
|
||||
if (!flag){
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
private void swap(int[] arr,int i,int j){
|
||||
int temp=arr[i];
|
||||
arr[i]=arr[j];
|
||||
arr[j]=temp;
|
||||
}
|
||||
}
|
56
src/main/java/sort/MergeSort.java
Normal file
56
src/main/java/sort/MergeSort.java
Normal file
@ -0,0 +1,56 @@
|
||||
package sort;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class MergeSort {
|
||||
|
||||
/**
|
||||
* 归并排序(入口函数)
|
||||
* @param arr 待排序数组
|
||||
*/
|
||||
public static void mergeSort(int[] arr) {
|
||||
if (arr == null || arr.length <= 1) {
|
||||
return; // 边界条件
|
||||
}
|
||||
int[] temp = new int[arr.length]; // 辅助数组
|
||||
mergeSort(arr, 0, arr.length - 1, temp);
|
||||
}
|
||||
|
||||
private static void mergeSort(int[] arr, int left, int right, int[] temp) {
|
||||
if (left < right) {
|
||||
int mid = (right + left) / 2;
|
||||
mergeSort(arr, left, mid, temp); // 递归左子数组
|
||||
mergeSort(arr, mid + 1, right, temp); // 递归右子数组
|
||||
merge(arr, left, mid, right, temp); // 合并两个有序子数组
|
||||
}
|
||||
}
|
||||
|
||||
private static void merge(int[] arr, int left, int mid, int right, int[] temp) {
|
||||
int i = left; // 左子数组起始指针
|
||||
int j = mid + 1; // 右子数组起始指针
|
||||
int t = 0; // 辅助数组指针
|
||||
|
||||
// 1. 按序合并两个子数组到temp
|
||||
while (i <= mid && j <= right) {
|
||||
if (arr[i] <= arr[j]) { // 注意等号保证稳定性
|
||||
temp[t++] = arr[i++];
|
||||
} else {
|
||||
temp[t++] = arr[j++];
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 将剩余元素拷贝到temp
|
||||
while (i <= mid) {
|
||||
temp[t++] = arr[i++];
|
||||
}
|
||||
while (j <= right) {
|
||||
temp[t++] = arr[j++];
|
||||
}
|
||||
|
||||
// 3. 将temp中的数据复制回原数组
|
||||
t = 0;
|
||||
while (left <= right) {
|
||||
arr[left++] = temp[t++];
|
||||
}
|
||||
}
|
||||
}
|
46
src/main/java/sort/QuickSort.java
Normal file
46
src/main/java/sort/QuickSort.java
Normal file
@ -0,0 +1,46 @@
|
||||
package sort;
|
||||
|
||||
public class QuickSort {
|
||||
|
||||
// 交换数组中两个元素的位置
|
||||
public void quickSort(int[] arr, int begin, int end) {
|
||||
if (begin >= end) {
|
||||
return;
|
||||
}
|
||||
//划分为满足上述条件的两个子表,返回基准位置
|
||||
int pos=partition(arr,begin,end);
|
||||
//对两个子表进行递归排序
|
||||
quickSort(arr, begin, pos - 1);
|
||||
quickSort(arr, pos + 1, end);
|
||||
}
|
||||
//划分左右子序列,返回基准位置
|
||||
public int partition(int[] arr, int i, int j){
|
||||
int temp = arr[i];
|
||||
while (i < j) {
|
||||
//在右边找到小于temp的放到左边
|
||||
while (i < j && arr[j] >= temp) {
|
||||
j--;
|
||||
}
|
||||
arr[i] = arr[j];
|
||||
//在左边找到大或等于于temp的放到右边
|
||||
while (i < j && arr[i] <= temp) {
|
||||
i++;
|
||||
}
|
||||
arr[j] = arr[i];
|
||||
}
|
||||
//将temp放在剩下的基准位置i、j均可
|
||||
arr[i] = temp;
|
||||
return i;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int[] arr = {49, 38, 65, 97, 76, 13, 27, 49};
|
||||
QuickSort solution = new QuickSort();
|
||||
solution.quickSort(arr, 0, arr.length - 1);
|
||||
|
||||
System.out.println("\n排序后:");
|
||||
for (int num : arr) {
|
||||
System.out.print(num + " ");
|
||||
}
|
||||
}
|
||||
}
|
15
src/test/java/greedy/FindContentChildrenTest.java
Normal file
15
src/test/java/greedy/FindContentChildrenTest.java
Normal file
@ -0,0 +1,15 @@
|
||||
package greedy;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class FindContentChildrenTest {
|
||||
|
||||
@Test
|
||||
public void findContentChildren() {
|
||||
int[] g = {1,2,3}, s = {1,1};
|
||||
FindContentChildren solution = new FindContentChildren();
|
||||
int res=solution.findContentChildren(g,s);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user