📜个人简介 |
⭐️个人主页:摸鱼の文酱博客主页🙋♂️
🍑博客领域:java编程基础,mysql
🍅写作风格:干货,干货,还是tmd的干货
🌸精选专栏:【Java】【mysql】 【算法刷题笔记】
🎯博主的码云gitee,平常博主写的程序代码都在里面。
🚀支持博主:点赞👍、收藏⭐、留言💬
🍭作者水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!
文章目录
题目链接 | 难度 |
---|---|
1464. 数组中两元素的最大乘积 | easy |
1217. 玩筹码 | easy |
1029. 两地调度 | medium |
面试题 10.11. 峰与谷 | medium |
📃1464. 数组中两元素的最大乘积
🎯解题思路
📒思路一:暴力
分别计数L和R的次数,每当两个出现次数相同时分割一次,同时再把L和R数量置为0
public static int balancedStringSplit(String s) {
int R_count = 0;
int L_count = 0;
int count = 0;
for (int i = 0; i < s.length(); i++) {
if(s.charAt(i) == 'R'){
R_count++;
} else {
L_count++;
}
if(R == L){
count++;
R_count=0;
L_count=0;
}
}
return count;
}
📒思路二:贪心
根据题意,对于一个平衡字符串 s,若 s 能从中间某处分割成左右两个子串,若其中一个是平衡字符串,则另一个的L 和R 字符的数量必然是相同的,所以也一定是平衡字符串。
为了最大化分割数量,我们可以不断循环,每次从 s 中分割出一个最短的平衡前缀,由于剩余部分也是平衡字符串,我们可以将其当作 s 继续分割,直至 s 为空时,结束循环。
代码实现中,可以在遍历 s 时用一个变量 d 维护L 和 R 字符的数量之差,当 d=0 时就说明找到了一个平衡字符串,将答案加一。
class Solution {
public int balancedStringSplit(String s) {
int ans = 0, d = 0;
for (int i = 0; i < s.length(); ++i) {
char ch = s.charAt(i);
if (ch == 'L') {
++d;
} else {
--d;
}
if (d == 0) {
++ans;
}
}
return ans;
}
}
📃1217. 玩筹码
🎯解题思路
📒思路一:贪心
1. 偶数变偶数,奇数变奇数,没有代价
2. 偶数变奇数,奇数变偶数,代价为1
统计奇数和偶数的数量,取奇数和偶数数量较小的那个数量便是所求的代价。
/*
贪心策略(思路)
1.尽量多用代价为0的方式移动,将所有筹码移动到最接近,然后在用代价为1的方式移动筹码,知道筹码位置相同
2.由1可知如果最终位置为奇数,则原本奇数位置移动的代价为0,偶数位置移动的代价为1
如果最终位置为偶数,则原本偶数位置移动的代价为0,奇数位置移动的代价为1
3.【先统计奇数位置和偶数位置元素的个数,哪个少代价就是多少】
*/
class Solution {
public int minCostToMoveChips(int[] position) {
int[] num = new int[2]; //记录奇数和偶数的个数
for (int i = 0; i < position.length; i++) {
if (position[i] % 2==0){
num[0]++;
}else {
num[1]++;
}
}
return Math.min(num[0],num[1]); //返回较小的数
}
}
📃1029. 两地调度
🎯解题思路
📒思路一:贪心
首先就需要对数组进行排序,但是如何排序?以哪个值来排序呢?
如果我们以 c o s t A cost_A costA来进行排序,那么当 P e r s o n X c o s t A < P e r s o n Y c o s t A Person X cost_A < Person Y cost_A PersonXcostA<PersonYcostA,同时 P e r s o n X c o s t B > > P e r s o n Y c o s t B Person X cost_B >> Person Y cost_B PersonXcostB>>PersonYcostB时,我们选择 P e r s o n X 去 C i t y A Person X去City A PersonX去CityA,那么很明显总和会更大,同理 c o s t A cost_A costA也不能。
那么以哪个值来进行排序呢?
假如让 2 ∗ n 2*n 2∗n个人都去 c i t y B city B cityB, 然后在其中选择 n n n个人去 c i t y A city A cityA,那么这些人公司需要额外付 p r i c e A − p r i c e B price_A - price_B priceA−priceB.
最后我们得到了答案,那就是根据 p r i c e A − p r i c e B price_A - price_B priceA−priceB来进行排序,前 n n n个人去 c i t y A city A cityA, 后面的去 c i t y B city B cityB。
public static int twoCitySchedCost(int[][] costs) {
int len = costs.length;
int[][] diff = new int[len][2];
for (int i = 0; i < len; i++) {
diff[i][0] = i;
diff[i][1] = costs[i][0] - costs[i][1];
}
Arrays.sort(diff, (o1, o2) -> {
if (o1[1] == o2[1]) {
return o1[0] - o2[0];
}
return o1[1] - o2[1];
});
int ans = 0;
for (int i = 0; i < len / 2; i++) {
ans += costs[diff[i][0]][0];
}
for (int i = len / 2; i < len; i++) {
ans += costs[diff[i][0]][1];
}
return ans;
}
//优化
public static int twoCitySchedCost_opt(int[][] costs) {
Arrays.sort(costs, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[0] - o1[1] - (o2[0] - o2[1]);
}
});
int len = costs.length;
int n = len / 2;
int sum = 0;
for (int i = 0; i < n; i++) {
sum += costs[i][0] + costs[i + n][1];
}
return sum;
}
📒思路二:DP
public static int twoCitySchedCost_dp(int[][] costs) {
int n = costs.length / 2;
int[][] dp = new int[n + 1][n + 1];
for (int i = 1; i <= n; i++) {
dp[i][0] = dp[i - 1][0] + costs[i - 1][0];
dp[0][i] = dp[0][i - 1] + costs[i - 1][1];
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
dp[i][j] = Math.min(dp[i - 1][j] + costs[i + j - 1][0], dp[i][j - 1] + costs[i + j - 1][1]);
}
}
return dp[n][n];
}
📒思路三:递归
public static int twoCitySchedCost_rec(int[][] costs) {
int n = costs.length / 2;
int[][] dp = new int[2 * n][2 * n];
return helper(dp, costs, 0, 0);
}
public static int helper(int[][] dp, int[][] costs, int idx, int cityA) {
if (idx == costs.length) {
return 0;
}
if (dp[idx][cityA] > 0) {
return dp[idx][cityA];
}
int n = costs.length / 2;
// n persons arrived to second city
if (idx - cityA == n) {
return dp[idx][cityA] = costs[idx][0] + helper(dp, costs, idx + 1, cityA + 1);
} else if (cityA == n) { // n persons arrived to first city
return dp[idx][cityA] = costs[idx][1] + helper(dp, costs, idx + 1, cityA);
} else {
return dp[idx][cityA] = Math.min(costs[idx][1] + helper(dp, costs, idx + 1, cityA), costs[idx][0] + helper(dp, costs, idx + 1, cityA + 1));
}
}
📃面试题 10.11. 峰与谷
🎯解题思路
📒思路一:排序
首先就对数组进行排序,将排序后的数组按照一个最大值后接一个最小值分配
class Solution {
public void wiggleSort(int[] nums) {
int idx = 0, len = nums.length;
if (len < 3) return;
int low = 0, high = len - 1;
int[] sorted = Arrays.copyOf(nums, len);
Arrays.sort(sorted);
while (low < high) {
nums[idx++] = sorted[high--];
nums[idx++] = sorted[low++];
}
if (len % 2 > 0)
nums[idx] = sorted[low];
}
}
📒思路二:遍历
遍历数组,保证数组在局部为谷-峰-谷
class Solution {
public void wiggleSort(int[] nums) {
int n = nums.length;
for (int i = 1; i < n; ++i)
if ((i & 1) == 1 ? nums[i] < nums[i - 1] : nums[i] > nums[i - 1])
swap(nums, i, i - 1);
}
private void swap(int[] nums, int idx1, int idx2) {
nums[idx1] ^= nums[idx2];
nums[idx2] ^= nums[idx1];
nums[idx1] ^= nums[idx2];
}
}