Leetcode787,870 Java

787. K 站中转内最便宜的航班

有 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()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值