给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
示例:
输入: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”],
输出:
[
[“ate”,“eat”,“tea”],
[“nat”,“tan”],
[“bat”]
]
说明:
所有输入均为小写字母。
不考虑答案输出的顺序。
备注:
思路就是对异位词进行hash计算,使它们能计算出一个相同的key来
public static List<List<String>> groupAnagrams(String[] strs) {
if (strs == null || strs.length == 0) {
return null;
}
HashMap<String, List<String>> map = new HashMap<>();
int count[] = new int[26];
for (String str : strs) {
Arrays.fill(count, 0);
for (char c : str.toCharArray()) {
count[c - 97]++;
}
// 替换所有非数字字符,非必须
String key = Arrays.toString(count).replaceAll("\\D", "");
if (!map.containsKey(key)) {
map.put(key, new ArrayList<>());
}
map.get(key).add(str);
}
return new ArrayList<>(map.values());
}
讨论区
在美版leetcode上看到大神的思路,用质数表示26个字母,把字符串的各个字母相乘,这样可保证字母异位词的乘积必定是相等的。其余步骤就是用map存储。
给定一个整数数组nums,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
进阶:
class Solution {
public int maxSubArray(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int ans = nums[0];
for (int i = 1; i < nums.length; i++) {
nums[i] += Math.max(nums[i - 1], 0);
ans = Math.max(ans, nums[i]);
}
return ans;
}
}
class Solution {
public int maxSubArray(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int sum, tmpSum;
tmpSum = nums[0];
sum = nums[0];
for (int i = 1; i < nums.length; i++) {
tmpSum = tmpSum > 0 ? tmpSum + nums[i] : nums[i];
sum = Math.max(sum, tmpSum);
}
return sum;
}
}
- 合并区间
给出一个区间的集合,请合并所有重叠的区间。
示例 1:
输入: [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
备注:
耗时比较久,68ms
public static List<Interval> merge(List<Interval> intervals) {
if (intervals == null || intervals.size() == 0) {
return intervals;
}
// 先按start排序
intervals.sort((la, lb) -> la.start - lb.start);
Interval pre = intervals.get(0);
Interval cur = null;
for (int i = 1; i < intervals.size();) {
cur = intervals.get(i);
// 不能合并
if (cur.start > pre.end) {
pre = cur;
// 重要
i++;
} else {
pre.end = Math.max(pre.end, cur.end);
intervals.remove(i);
}
}
return intervals;
}
一个机器人位于一个m x n 网格的左上角。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角,问总共有多少条不同的路径?
备注:
…没看出来这是组合数
带空间压缩版本
class Solution {
public int uniquePaths(int m, int n) {
int[] dp = new int[n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
dp[j] = (i == 0 || j == 0) ? 1 : dp[j - 1] + dp[j];
}
}
return dp[n - 1];
}
}
二维数组版本
public static int uniquePaths(int m, int n) {
// dp[i][j]代表从0,0到i,j的方法数
int dp[][] = new int[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
dp[i][j] = (i == 0 || j == 0) ? 1 : dp[i - 1][j] + dp[i][j - 1];
}
}
return dp[m - 1][n - 1];
}
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1或2个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2解释: 有两种方法可以爬到楼顶。
- 1 阶 + 1 阶
- 2 阶
示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
- 1 阶 + 1 阶 + 1 阶
- 1 阶 + 2 阶
- 2 阶 + 1 阶
class Solution {
public int climbStairs(int n) {
int f1,f2;
f1 = f2 = 1;
int ans = 1;
for(int i = 2;i<=n;i++){
ans = f1 + f2;
f1 = f2;
f2 = ans;
}
return ans;
}
}