有 n 个城市通过一些航班连接。给你一个数组 flights ,其中 flights[i] = [fromi, toi, pricei] ,表示该航班都从城市 fromi 开始,以价格 pricei 抵达 toi。
现在给定所有的城市和航班,以及出发城市 src 和目的地 dst,你的任务是找到出一条最多经过 k 站中转的路线,使得从 src 到 dst 的 价格最便宜 ,并返回该价格。 如果不存在这样的路线,则输出 -1。
示例 1:
输入:
n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
src = 0, dst = 2, k = 1
输出: 200
从城市 0 到城市 2 在 1 站中转以内的最便宜价格是 200,如图中红色所示。
示例 2:
输入:
n = 3, edges = [[0,1,100],[1,2,100],[0,2,500]]
src = 0, dst = 2, k = 0
输出: 500
从城市 0 到城市 2 在 0 站中转以内的最便宜价格是 500
// 自底向上迭代法
public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) {
final int INF = 100000;
int[][] dp = new int[n][k+2];
for(int[] row : dp)
Arrays.fill(row,INF);
dp[src][0] = 0;
for(int i=1;i<k+2;i++) {
for(int[] flight : flights){
int from = flight[0], to = flight[1], cost = flight[2];
dp[to][i] = Math.min(dp[to][i], dp[from][i-1]+cost);
}
}
int res = INF;
for(int i=0;i<k+2;i++)
res = Math.min(res, dp[dst][i]);
return res==INF?-1:res;
}
//自顶向下递归法(带备忘录)
class Solution {
HashMap<Integer,List<int[]>> indegree;
int src,dst;
int[][] memo;
public int findCheapestPrice(int n, int[][] flights, int src, int dst, int k) {
k++;
this.src = src;
this.dst = dst;
indegree = new HashMap<>();
memo = new int[n][k+1];
for(int[] row : memo)
Arrays.fill(row,-100);
for(int[] f : flights) {
int from = f[0];
int to = f[1];
int price = f[2];
indegree.putIfAbsent(to,new LinkedList<>());
indegree.get(to).add(new int[] {from,price});
}
return dp(dst,k);
}
int dp(int s,int k) {
if(s == src) return 0;
if(k == 0) return -1;
if(memo[s][k] != -100)
return memo[s][k];
int res = Integer.MAX_VALUE;
if(indegree.containsKey(s)){
for(int[] v : indegree.get(s)){
int from = v[0];
int price = v[1];
int subProm = dp(from,k-1);
if(subProm != -1)
res = Math.min(res, subProm + price);
}
}
memo[s][k] = res==Integer.MAX_VALUE?-1:res;
return memo[s][k];
}
}
小结:动态规划,三步走:第一步找到变化的状态,确定dp数组含义;第二步写出状态转移方程;第三步确定 base
1.本题当中变化的状态为可以走的步数 k 和目的地 s;dp[s][k] 表示走k步能到达s点的最短距离。题目中的k为可中转的城市,dp数组中的k表示目标城市到源城市之间的边数,因此k需要加1.题目要求的为 dp[dst][k+1]
2.dp[s][k] = min(dp[s][k],dp[s的前一个城市][k-1]),多叉树的遍历
3.d[src][0] = 0
870. 优势洗牌
给定两个大小相等的数组 A 和 B,A 相对于 B 的优势可以用满足 A[i] > B[i] 的索引 i 的数目来描述。
返回 A 的任意排列,使其相对于 B 的优势最大化
示例 1:
输入:A = [2,7,11,15], B = [1,10,4,11]
输出:[2,11,7,15]
示例 2:
输入:A = [12,24,8,32], B = [13,25,32,11]
输出:[24,32,8,12]
class Solution {
public int[] advantageCount(int[] nums1, int[] nums2) {
int n = nums1.length;
Arrays.sort(nums1);
PriorityQueue<int[]> p = new PriorityQueue<>(
(int[] pair1, int[] pair2)->{
return pair2[1] - pair1[1];
}
);
for(int i=0;i<n;i++)
p.offer(new int[] {i,nums2[i]});
int[] res = new int[n];
int right = n-1;
int left = 0;
while(!p.isEmpty()){
int[] temp = p.poll();
int index = temp[0];
int maxV = temp[1];
if(maxV < nums1[right])
res[index] = nums1[right--];
else
res[index] = nums1[left++];
}
return res;
}
}
思路:把 nums1 排序,nums2 其实也想排序,但由于不能改变它的顺序,因此只能把它放进优先队列,使他索引和值仍能对应
打得过就打,打不过就拿最小的互换
Java 语法:
1.初始化二维数组:
for(int[] row : arrays)
Arrays.fill(row,value)
2.最大最小值
Math.min(),Math.max(),Integer.MAX_VALUE,Integer.MIN_VALUE
3.HashMap 添加元素,判断是否Map中是否存在某key
mp.putIfAbsent(key,value) 如果不存在key,则put,否则不作处理
mp.containsKey(key)
4.List 插入元素与查找元素
list.add(s)
list.get(s)
5.定义临时List与数组
new LinkedList<>()
new int[] {v1,v2}
6.给数组排序
Arrays.sort(array)
7.定义元素为一维数组的优先队列并按数组的第二个元素降序排序
PriorityQueue<int[]> q = new PriorityQueue<>(
(int[] pair1,int[] pair2)->{
return pair2[1]-pair1[1];
}
);
8.插入、删除并返回堆顶元素、判空优先队列
q.offer(e) q.poll() q.isEmpty()