3月25日阿里实习笔试后的反思

一、原题回顾

* 给定一个3行n列的数组。需要从这n列中,每列中都选择一个数字出来,然后要求这组数据中,每相邻的两个元素的差的绝对值的累加和是最小的。输出最小的累加和即可。
* 输入示例:第一行为n的值,后面为数组。
* 5
* 5 9  5  4   4
* 4 7  4  10  3
* 2 10 9  2   3
* 这里可以选择[5, 7, 5, 4, 4],因为2 + 2 + 1 + 0 = 5。是最小的累加和。输出5即可。

二、思路回顾

       其实拿到这个题目之后,第一反应肯定是一致的,就是dp,使用动态规划来做。甚至我都能想得到是通过一步步的局部最优解,然后得到最后的全局最优解。然而,最后实现起来的时候,却困难重重,再次印证了“紧张是写不出清晰的代码的”。哎,现在回头看,其实之前也做过一些dp,也十分清楚一旦dp,就最好设一个数组。结果当时竟然只想了设一个int [n] 大小的一位数组给dp,然后就陷入了困境。加上之后各种下标,把自己弄的晕乎乎的,哎,最后也没有做出来。

        所以,后面一定要把dp的题目加强练习,特别是总结整理好思路,然后多练习,加强思路的快速实现。加油加油。

        做题思路:建立和原数据一样大小的dp二维数组,除了第一列都初始化为0,后面的每一列中的第i行的元素,都代表在这一列选择第i行的这一个数字后,分别在前一行选择第0或者第1或者第2个数字,这三种情况中,可以获得的最小值。最后再从dp的最后一列中找最小值。

三、原题的解答。

import java.util.Scanner;

/**
 * @Author: lei
 * @Data: 2020.3.24 11:22
 * @Description: 3.25阿里笔试题1
*/

public class AliTest1 {
	public static void main(String [] args) {
		//输入数据的处理
		Scanner in = new Scanner(System.in);  //列数
		int n = in.nextInt();
		int [][] a = new int[3][n];  //数据存放
		for(int i = 0;i < 3;i++){
			for(int j = 0;j < n;j++){
				a[i][j] = in.nextInt();
			}
		}
		int [][] dp = new int[3][n];
		dp[0][0] = dp[1][0] = dp[2][0] = 0;  //最开始的一行差值都设置为0
		for(int i = 1;i < n;i++){
			//dp[0][i]代表了:在第i列 选择了第0行的那个数字的情况下,可以获得的最小绝对值。(因此就要考虑三种情况:i-1行选择第0行或者第1行或者第2行的数字)
			//在这三种情况中,既要算这三个数分别与 第i列第0行的那个数字 的差值的绝对值,还要加上它们各自对应的dp数组中的值,就是之前的局部最优解。
			dp[0][i] = get_min(Math.abs(a[0][i-1]-a[0][i]) + dp[0][i-1], Math.abs(a[1][i-1]-a[0][i]) + dp[1][i-1],Math.abs(a[2][i-1]-a[0][i]) + dp[2][i-1]);
			dp[1][i] = get_min(Math.abs(a[0][i-1]-a[1][i]) + dp[0][i-1], Math.abs(a[1][i-1]-a[1][i]) + dp[1][i-1],Math.abs(a[2][i-1]-a[1][i]) + dp[2][i-1]);
			dp[2][i] = get_min(Math.abs(a[0][i-1]-a[2][i]) + dp[0][i-1], Math.abs(a[1][i-1]-a[2][i]) + dp[1][i-1],Math.abs(a[2][i-1]-a[2][i]) + dp[2][i-1]);
		}
		System.out.println(get_min(dp[0][n-1], dp[1][n-1], dp[2][n-1]));  //最后再从末尾一行中的 三个dp值 中选择最小的那个。
	}
	
	//获取三个数中的最小值
	public static int get_min(int a, int b, int c){
		return Math.min(a, Math.min(b, c));
	}
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值