栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

刷力扣的一些记录

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

刷力扣的一些记录

基本知识

StringBuilder&StringBuffer&&String

StringBuilder类也代表可变字符串对象。实际上,StringBuilder和StringBuffer基本相似,两个类的构造器和方法也基本相同。不同的是:StringBuffer是线程安全的,而StringBuilder则没有实现线程安全功能,所以性能略高。

一旦通过StringBuffer生成了最终想要的字符串,就可以调用它的toString()方法将其转换为一个String对象。

String类是不可变类,即一旦一个String对象被创建以后,包含在这个对象中的字符序列是不可改变的,直至这个对象被销毁。

String a = "123";
a = "456";
// 打印出来的a为456
System.out.println(a)

可以看出来,再次给a赋值时,并不是对原来堆中实例对象进行重新赋值,而是生成一个新的实例对象,并且指向“456”这个字符串,a则指向最新生成的实例对象,之前的实例对象仍然存在,如果没有被再次引用,则会被垃圾回收。

Map.getOrDefault(Object key, V defaultValue)

Map.getOrDefault(Object key, V defaultValue)方法的作用是:
  当Map集合中有这个key时,就使用这个key值;
  如果没有就使用默认值defaultValue。

HashMap map = new HashMap<>();
map.put("name", "cookie");
map.put("age", "18");
map.put("sex", "女");
String name = map.getOrDefault("name", "random");
System.out.println(name);// cookie,map中存在name,获得name对应的value
int score = map.getOrDefault("score", 80);
System.out.println(score);// 80,map中不存在score,使用默认值80

双目移位运算符 >>1 和 /2 哪个更快?

速度很可能是一样快。建议,不要使用移位代替乘除。

Stack.peek()和Stack.pop()的区别

  1. Stack.peek()
peek()函数返回栈顶的元素,但不弹出该栈顶元素。
  1. Stack.pop()
pop()函数返回栈顶的元素,并且将该栈顶元素出栈。

Map集合中不应该利用get()方法来判断是否存在某个键,而应该利用containsKey()方法来判断

LinkedList 是一个继承于AbstractSequentialList的双向链表。它也可以被当作堆栈、队列或双端队列进行操作

交换和反转

public void swap(int[] nums, int i, int j) {
    int temp = nums[i];
    nums[i] = nums[j];
    nums[j] = temp;
}

public void reverse(int[] nums, int start) {
    int left = start, right = nums.length - 1;
    while (left < right) {
        swap(nums, left, right);
        left++;
        right--;
    }
}

new String()和toString()的区别

str.toString是调用了该对象的类的toString方法。一般是返回这么一个String:[class name]@[hashCode]。
new String(str)是使用java虚拟机默认的编码格式,将这个字节数组转换为对应的字符。若虚拟机默认的编码格式是ISO-8859-1,按照ascii编码表即可得到字节对应的字符。
new String()一般用在将字节数组转为字符串的时候
toString()一般用在输出某个对象的时候

问题(来源于leetcode):

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 
class Solution {
    public List> groupAnagrams(String[] strs) {
        Map> map=new HashMap>();
        for(String str:strs){
            char[] array=str.toCharArray();
            Arrays.sort(array);//传数组 先排序
//            String key=array.toString();不能用这个???
            String key=new String(array);
            List list=map.getOrDefault(key,new ArrayList());
            list.add(str);
            map.put(key,list);
        }
        return new ArrayList>(map.values());

测试:

char[] array={'a','b'};
String key = array.toString();//[C@1d56ce6a   地址 每次地址都不一样 key当然也不会一样 因此会有这样如下测试结果
System.out.println(key);
String key2 = new String(array);//ab    值
System.out.println(key2);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WTDItSef-1654156134512)(C:Users50537AppDataRoamingTyporatypora-user-imagesimage-20220519114000686.png)]

关于Array和List的区别

1.Array连续 List不连续 因此定义时需要指定Array长度

2.查找Array 插入List

动态规划

动态规划的三大步骤

利用历史记录,来避免重复计算。而这些历史记录,我们得需要一些变量来保存,一般是用一维数组或者**二维数组来保存。
第一步骤:定义数组元素的含义**,用一个数组,来保存历史数组,假设用一维数组 dp[] 你的 dp[i] 是代表什么意思?

第二步骤:找出数组元素之间的关系式
第三步骤:找出**初始值**。

判断数组等数据结构不越界需要放在条件的前面

如

else if (i - dp[i - 1] > 0 && s.charAt(i - dp[i - 1] - 1) == '(') 

反过来就会报错 必须保证先不出界才能继续后面条件判断双指针

这个方法就是我们常说的「双指针」,当我们需要枚举数组中的两个元素时,如果我们发现随着第一个元素的递增,第二个元素是递减的,那么就可以使用双指针的方法,

将给定数字序列重新排列成字典序中下一个更大的排列。

爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

通项公式: f(x)=f(x−1)+f(x−2) 滚动数组

public int climbStairs(int n) {
//        动态规划 滚动数组 初始值 通项公式
                int p = 0, q = 0, r = 1;//第0层
                for (int i = 1; i <= n; i++) {
                    p = q;
                    q = r;
                    r = p + q;
                }
                return r;
            }
 
回溯 
def backtrack(...):
    for 选择 in 选择列表:
        做选择
        backtrack(...)
        撤销选择
1、路径:也就是已经做出的选择。

2、选择列表:也就是你当前可以做的选择。

3、结束条件:也就是到达决策树底层,无法再做选择的条件。
result = []
def backtrack(路径, 选择列表):
    if 满足结束条件:
        result.add(路径)
        return

    for 选择 in 选择列表:
        做选择
        backtrack(路径, 选择列表)
        撤销选择
例题1

if的两个选择 括号匹配

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VLwaKcgu-1654156134515)(C:Users50537AppDataRoamingTyporatypora-user-imagesimage-20220420170037385.png)]

例题2
//给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的
// 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。 
class Solution {
    public List> combinationSum(int[] candidates, int target) {
        List> ans=new ArrayList<>();
        List cur=new ArrayList<>();
        backtrack(candidates,target,ans,cur,0,0);
        return ans;
    }
    public void backtrack(int[] candidates,int target,List> ans,List cur,int sum,int index) {
        if (sum == target) {
            ans.add(new ArrayList(cur));
            //此处为啥不是ans.add(cur)?
            //答案:因为cur是数组的引用地址,直接add最后是空的

            return;
        }

        if (sum < target) {
            //index的作用是为了使得不出现 测试结果:[[2,2,3],[2,3,2],[3,2,2],[7]] 期望结果:[[2,2,3],[7]]
            //这种情况,保持数组cur升序,也就避免了重复
            for (int i = index; i < candidates.length; i++) {
                cur.add(candidates[i]);
                sum = sum + candidates[i];
                backtrack(candidates, target, ans, cur, sum,i);//i传进去
                cur.remove(cur.size() - 1);
                sum = sum - candidates[i];//剪枝操作 返回回原来状态 否则sum只会越来越大
            }
        }
    }

}
例题3

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aEvGgExB-1654156134515)(C:Users50537AppDataRoamingTyporatypora-user-imagesimage-20220531161347850.png)]

vector t;
void dfs(int cur, int n) {
    if (cur == n) {
        // 记录答案
        // ...
        return;
    }
    // 考虑选择当前位置
    t.push_back(cur);
    dfs(cur + 1, n, k);
    t.pop_back();
    // 考虑不选择当前位置
    dfs(cur + 1, n, k);
}
递归

public ListNode mergeTwoLists(ListNode list1,ListNode list2){
    if(list1==null||list2==null){
        return list1==null?list2:list1;
    }else if(list1.val
        list1.next=mergeTwoLists(list1.next,list2);
        return list1;
    }else{
        list2.next=mergeTwoLists(list2.next,list1);
        return list2;
    }
}


数学、规律 通项公式

力扣48题翻转矩阵

只关注我画黑框的部分 其余三块都是每个元素旋转而成

//        官方第二种方法
        class Solution {
            public void rotate(int[][] matrix) {
                int n = matrix.length;
                for (int i = 0; i < n / 2; ++i) {//行数 向下区取余
                    for (int j = 0; j < (n + 1) / 2; ++j) {//列数 加一再向下取余
                        int temp = matrix[i][j];
                        matrix[i][j] = matrix[n - j - 1][i];
                        matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];
                        matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];
                        matrix[j][n - i - 1] = temp;
                    }
                }
            }
        }

最终解法 将旋转分解为水平翻转和主对角线翻转(因为这俩翻转都是俩俩交换 直接temp换就完事儿,而旋转是4个元素在换)

class Solution {
    public void rotate(int[][] matrix) {
        int n = matrix.length;
        // 水平翻转
        for (int i = 0; i < n / 2; ++i) {
            for (int j = 0; j < n; ++j) {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[n - i - 1][j];
                matrix[n - i - 1][j] = temp;
            }
        }
        // 主对角线翻转
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < i; ++j) {
                int temp = matrix[i][j];
                matrix[i][j] = matrix[j][i];
                matrix[j][i] = temp;
            }
        }
    }
}

二分

部分有序也可以二分

旋转数组:
将数组一分为二,其中一定有一个是有序的,另一个可能是有序,也能是部分有序。
此时有序部分用二分法查找。无序部分再一分为二,其中一个一定有序,另一个可能有序,可能无序。就这样循环. 
小技巧

一些变量符号

表示数量的话用cnt

flag表示标志,一般为正负

IDEA插件LeetEditor

出现cookie问题 怎么办?在idea进行插件更新!这是没想到的!
temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
}
}
}

## 二分

部分有序也可以二分

```yaml
旋转数组:
将数组一分为二,其中一定有一个是有序的,另一个可能是有序,也能是部分有序。
此时有序部分用二分法查找。无序部分再一分为二,其中一个一定有序,另一个可能有序,可能无序。就这样循环. 
小技巧

一些变量符号

表示数量的话用cnt

flag表示标志,一般为正负

IDEA插件LeetEditor

出现cookie问题 怎么办?在idea进行插件更新!这是没想到的!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/947083.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号