• 算法日常训练12.5


    首先有个很大的进步,看见困难题我没选择做逃兵跑路,这点起码是进步了,虽然算法能力还是那么拉,但是起码敢不自量力地分析一下。。。还能看题解理解下。

     先找题解中最简单地一种超时方法开始理解,使用动态规划

    定义dp:dp[i]:前i个箱子所需的最小行程

    初始化:明显有dp[0]=0,其他的需要选最大值,因为要维护最小值

    状态转移公式:dp[i]=dp[j-1]+cost(j,i);cost(j,i)代表j到i范围内的箱子所需要的行程

    cost(i,j)怎么求:首先出去和回来都需要一次行程,初始化为2,遍历范围的箱子,如果有相同连续码头的箱子,就可以一次性都放了,加1,没连续遇见一个新码头就要加1

    箱子需要遍历,范围需要遍历两次,超时,但是比较好理解

    1. class Solution {
    2. public int boxDelivering(int[][] boxes, int portsCount, int maxBoxes, int maxWeight) {
    3. int len=boxes.length;
    4. int[] dp=new int[len+1];//dp[i]:运送前i个箱子所需要的最少行程
    5. Arrays.fill(dp,Integer.MAX_VALUE);
    6. dp[0]=0;//初始化
    7. for(int i=1;i<=len;i++){
    8. int sum=0;//保证重量不超过最大值
    9. for(int j=i;j>=1&&j>=i-maxBoxes+1;j--){//保证数量不超过最大值
    10. sum+=boxes[j-1][1];//累加重量
    11. if(sum>maxWeight) break;
    12. dp[i]=Math.min(dp[i],dp[j-1]+cost(j,i,boxes));
    13. }
    14. }
    15. return dp[len];
    16. }
    17. public int cost(int l,int r,int[][] boxes){
    18. int port=2;//仓库出去和回来都要一次行程
    19. int pre=boxes[l-1][0];//记录前一个箱子目标码头
    20. while(++l<=r){//遍历这个范围的箱子
    21. if(boxes[l-1][0]==pre) continue;//和前面的箱子相同就不用行程
    22. port++;//不然就要一次行程
    23. pre=boxes[l-1][0];//更新前一个码头
    24. }
    25. return port;
    26. }
    27. }

    这里的dp可以发现是维护一个滑动窗口中的最小值,第一次见,详细分析见 力扣大佬题解 

    总之就是需要优化每次找最小值的时间,我选择使用优先队列,感觉好理解一点,看了很久,这题有点超出我水平了,溜了,有缘回来再看。

    1. class Solution {
    2. public int boxDelivering(int[][] boxes, int portsCount, int maxBoxes, int maxWeight) {
    3. int len=boxes.length;
    4. int[] dp=new int[len+1];//dp[i]:运送前i个箱子所需要的最少行程
    5. Arrays.fill(dp,Integer.MAX_VALUE);
    6. dp[0]=0;//初始化
    7. PriorityQueue<int[]> q = new PriorityQueue<int[]>((a, b)->a[1] - b[1]);//数组中保存的分别是i下标,最少次数,重量
    8. int dif=0;//差值
    9. int wei=0;//保存重量
    10. for(int i=1;i<=len;i++){
    11. int cur = dp[i-1] + 2;
    12. dif += i >= 2 && boxes[i - 1][0] != boxes[i - 2][0] ? 1 : 0;//如果相同,代表多加了一次行程
    13. wei += boxes[i - 1][1]; //保存重量
    14. q.add(new int[]{i, cur - dif, boxes[i - 1][1] - wei});
    15. while (q.peek()[0] <= i - maxBoxes || q.peek()[2] + wei > maxWeight) q.poll();//超载
    16. dp[i] = q.peek()[1] + dif;
    17. }
    18. return dp[len];
    19. }
    20. }

    经典的搜索题,写了好几遍了

    遍历所有城市,使用used标志该城市是否访问过,没访问过就进行深搜,找到和他相连的城市都搜一遍。 

    1. class Solution {
    2. boolean[] used;
    3. public int findCircleNum(int[][] isConnected) {
    4. int res=0;//记录省份数量
    5. used=new boolean[isConnected.length];
    6. for(int i=0;i
    7. if(!used[i]){
    8. dfs(i,isConnected);
    9. res++;}
    10. }
    11. return res;
    12. }
    13. public void dfs(int i,int[][] isConnected){
    14. used[i]=true;
    15. for(int j=0;j0].length;j++){
    16. if(!used[j]&&isConnected[i][j]==1) dfs(j,isConnected);
    17. }
    18. }
    19. }

  • 相关阅读:
    二叉树的存储
    一幅长文细学TypeScript(一)——上手
    面试突击:为什么 TCP 需要 3 次握手?
    面试算法6:排序数组中的两个数字之和
    Apache DolphinScheduler源码分析(超详细)
    掌握高等数学、线性代数、概率论所需数学知识及标题建议
    chrome 中一个坑DIE的设置 | getUserMedia is not implemented in this browser解决办法
    Vmware 静态网络配置
    仿网易云音乐小程序-uniapp
    Hive3 单机版(含Derby 多用户及Spark on Hive)
  • 原文地址:https://blog.csdn.net/weixin_57695844/article/details/128183396