题目大意:
对角线遍历 II
给你一个列表 nums ,里面每一个元素都是一个整数列表。请你依照下面各图的规则,按顺序返回 nums 中对角线上的整数。
示例 1:

输入:nums = [[1,2,3],[4,5,6],[7,8,9]] 输出:[1,4,2,7,5,3,8,6,9]
示例 2:

输入:nums = [[1,2,3,4,5],[6,7],[8],[9,10,11],[12,13,14,15,16]]
输出:[1,6,2,8,7,3,9,4,12,10,5,13,11,14,15,16]
示例 3:
输入:nums = [[1,2,3],[4],[5,6,7],[8],[9,10,11]] 输出:[1,4,2,5,3,8,6,9,7,10,11]
示例 4:
输入:nums = [[1,2,3,4,5,6]] 输出:[1,2,3,4,5,6]
提示:
- 1 <= nums.length <= 10^5
- 1 <= nums[i].length <= 10^5
- 1 <= nums[i][j] <= 10^9
- nums 中最多有 10^5 个数字。
如果想查看本题目是哪家公司的面试题,请参考以下免费链接: https://leetcode.jp/problemdetail.php?id=1424
解题思路分析:
这道题是一道矩阵题目,不过如果我们使用暴力解遍历每一条对角线的话,时间复杂度会达到O(n^2),由于矩阵的长和宽都是10的5次方数量级,这种算法显然会TLE。仔细观察本题,实际上它是一个不规则的矩阵,也就是说他每一行的长度是不同的,另外题目也给出数字的规模不会超过10的5次方,因此我们需要变换一个角度去思考问题。
首先我们应该将所有的数字进行分组,分组的标准即是他们是否在同一对角线上。判断同一对角线上的数字的方法很简单,即任意位置的横坐标加上纵坐标,值相同的所有点一定在同一对角线上。比如点(2,0),(1,1),(0,2)。
解题时,我们建立一个HashMap,来记录每条对角线的上所有点,key为对角线的id(横坐标加纵坐标),value为该对角线上所有的数字。另外我们要注意一下存储的顺序,由于每条对角线上的数字是从下向上(行数)排列的,因此我们从矩阵的最后一行开始遍历比较好。这样我们能够保证每条对角线上的数字已经按照顺序排列。对于当前行,我们再遍历它的每一列上的数字,使用当前行加上当前列的和,计算出当前数字所属的对角线id,将该数字存入map中对应该id的集合即可。重复此步骤直到循环结束。
另外,对角线的排列是从左至右,也就是他们id的升序排列。我们从0循环至最大id,分别取出map中该对应id的对角线上的所有数字,顺序将其放入返回结果即可。
实现代码:
public int[] findDiagonalOrder(List<List<Integer>> nums) {
// 记录每条对角线上的数字
Map<Integer, List<Integer>> map = new HashMap<>();
// 最大对角线id
int maxId=0;
// 所有节点个数
int size=0;
// 从下向上循环每一行
for(int i=nums.size()-1;i>=0;i--){
// 取出当前行的所有数字
List<Integer> list = nums.get(i);
// 循环当前行的每一个数字
for(int j=0;j<list.size();j++){
// 当前数字所在对角线的id(行加列)
int id = i+j;
// 取得该对角线上的所有数字集合
List<Integer> l = map.getOrDefault(id, new ArrayList<>());
// 将当前数字加入集合
l.add(list.get(j));
// 将集合存入map
map.put(id, l);
// 更新最大对角线id
maxId=Math.max(maxId, id);
// 节点个数加一
size++;
}
}
// 初始化返回数组
int[] res = new int[size];
// 返回结果数组的当前下标
int index=0;
// 循环每一个对角线id
for(int i=0;i<=maxId;i++){
// 取得当前对角线上的所有数字
List<Integer> l = map.get(i);
// 将每个数字按顺序加入返回结果
for(int j=0;j<l.size();j++){
res[index++]=l.get(j);
}
}
return res;
}本题解法执行时间为32ms。
Runtime: 32 ms, faster than 91.28% of Java online submissions for Diagonal Traverse II.
Memory Usage: 74.9 MB, less than 100.00% of Java online submissions for Diagonal Traverse II.
本网站文章均为原创内容,并可随意转载,但请标明本文链接如有任何疑问可在文章底部留言。为了防止恶意评论,本博客现已开启留言审核功能。但是博主会在后台第一时间看到您的留言,并会在第一时间对您的留言进行回复!欢迎交流!
本文链接: https://leetcode.jp/leetcode-1424-diagonal-traverse-ii-解题思路分析/