三数之和
方法一 暴力解法
三重循环
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
if (nums[i] <= 0) {
for (int j = i + 1; j < nums.length; j++) {
for (int k = j + 1; k < nums.length; k++) {
if (nums[i] + nums[j] + nums[k] == 0) {
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[k]);
if (!result.contains(list)) {
result.add(list);
}
break;
}
}
}
}
}
return result;
}
方法二 双指针
先得到一个target,转化为两数之和,用头尾指针寻找目标数
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
if (nums.length<3){
return result;
}
Arrays.sort(nums);
for (int i=0;i<nums.length;i++){
if (i>0 && nums[i] == nums[i-1]){ //排除重复情况
continue;
}
int target = -nums[i];
int left = i+1;
int right = nums.length-1;
while (left < right){
if (nums[left]+nums[right]<target){
left++;
}else if (nums[left]+nums[right]>target){
right--;
}else if (nums[left]+nums[right]==target){
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[left]);
list.add(nums[right]);
result.add(list);
left++;
right--;
while (left<right && nums[left]==nums[left-1]){
left++;
}
while (left<right && nums[right]==nums[right+1]){
right--;
}
}
}
}
return result;
}
矩阵置零
方法一 使用额外的数组存放需要置零的行和列
public void setZeroes(int[][] matrix) {
Set<Integer> cols = new HashSet<Integer>();
Set<Integer> rows = new HashSet<Integer>();
int R = matrix.length;
int C = matrix[0].length;
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
if (matrix[i][j] == 0) {
rows.add(i);
cols.add(j);
}
}
}
for (int i = 0; i < R; i++) {
for (int j = 0; j < C; j++) {
if (rows.contains(i) || cols.contains(j)) {
matrix[i][j] = 0;
}
}
}
}
方法二 将第一行和第一列作为标志位,不需额外空间
public void setZeroes(int[][] matrix) {
int row = matrix.length;
int col = matrix[0].length;
boolean row_flag = false;
boolean col_flag = false;
for (int i = 0; i < row; i++) { //看第一列有没有0
if (matrix[i][0] == 0) {
col_flag = true;
break;
}
}
for (int i = 0; i < col; i++) { //看第一行有没有0
if (matrix[0][i] == 0) {
row_flag = true;
break;
}
}
for (int i = 1; i < row; i++) { //修改第一行、一列
for (int j = 1; j < col; j++) {
if (matrix[i][j] == 0) {
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}
for (int i = 1; i < row; i++) { //置为零
for (int j = 1; j < col; j++) {
if (matrix[i][0] == 0 || matrix[0][j] == 0) {
matrix[i][j] = 0;
}
}
}
//将第一行、第一列置零
if (row_flag) {
for (int i = 0; i < col; i++) {
matrix[0][i] = 0;
}
}
if (col_flag) {
for (int i = 0; i < row; i++) {
matrix[i][0] = 0;
}
}
}
字母异位词分组
方法一 哈希表+字符串排序
public List<List<String>> groupAnagrams(String[] strs) {
if (strs.length==0){
return new ArrayList<>();
}
Map<String ,List> hashMap = new HashMap<String, List>();
for(String s:strs){
char[] chars = s.toCharArray();
Arrays.sort(chars); //将s排序
String key = String.valueOf(chars);
if (!hashMap.containsKey(key)){ //若当前map里面没有这个key,就新建一个键值对
hashMap.put(key,new ArrayList());
}
hashMap.get(key).add(s); //将s加入键为key的映射中
}
return new ArrayList<>(hashMap.values());
}
方法二 26位数组存放每位字母出现的次数
public List<List<String>> groupAnagrams(String[] strs) {
if (strs.length==0){
return new ArrayList<>();
}
Map<String,List> ans = new HashMap<>();
int[] count = new int[26]; //创建大小为26的数组,存放每个字母出现的次数
for (String s:strs){
Arrays.fill(count,0); //用零去填充count
for (char c : s.toCharArray()){
count[c-'a']++;
}
StringBuilder stringBuilder = new StringBuilder();
for (int i=0;i<26;i++){
stringBuilder.append('#');
stringBuilder.append(count[i]);
}
String key = stringBuilder.toString();
if (!ans.containsKey(key)){
ans.put(key,new ArrayList()); //新建键值对
}
ans.get(key).add(s); //将字符串加入对应的映射中
}
return new ArrayList<>(ans.values());
}