刷力扣的一些记录

基本知识

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<String, String> 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<List<String>> groupAnagrams(String[] strs) {
        Map<String, List<String>> map=new HashMap<String, List<String>>();
        for(String str:strs){
            char[] array=str.toCharArray();
            Arrays.sort(array);//传数组 先排序
//            String key=array.toString();不能用这个???
            String key=new String(array);
            List<String> list=map.getOrDefault(key,new ArrayList<String>());
            list.add(str);
            map.put(key,list);
        }
        return new ArrayList<List<String>>(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:\Users\50537\AppData\Roaming\Typora\typora-user-images\image-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) == '(') 

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

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

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

fig1

爬楼梯

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

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

fig1
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;
            }
/* 动态规划五部曲:
     * 1.确定dp[i]的下标以及dp值的含义: 爬到第i层楼梯,有dp[i]种方法;
     * 2.确定动态规划的递推公式:dp[i] = dp[i-1] + dp[i-2];
     * 3.dp数组的初始化:因为提示中,1<=n<=45 所以初始化值,dp[1] = 1, dp[2] = 2;
     * 4.确定遍历顺序:分析递推公式可知当前值依赖前两个值来确定,所以递推顺序应该是从前往后;
     * 5.打印dp数组看自己写的对不对;
    */

回溯

def backtrack(...):
    for 选择 in 选择列表:
        做选择
        backtrack(...)
        撤销选择
1、路径:也就是已经做出的选择。

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

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

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

例题1

if的两个选择 括号匹配

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VLwaKcgu-1654156134515)(C:\Users\50537\AppData\Roaming\Typora\typora-user-images\image-20220420170037385.png)]

例题2

//给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的
// 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。 
class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> ans=new ArrayList<>();
        List<Integer> cur=new ArrayList<>();
        backtrack(candidates,target,ans,cur,0,0);
        return ans;
    }
    public void backtrack(int[] candidates,int target,List<List<Integer>> ans,List<Integer> cur,int sum,int index) {
        if (sum == target) {
            ans.add(new ArrayList<Integer>(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:\Users\50537\AppData\Roaming\Typora\typora-user-images\image-20220531161347850.png)]

vector<int> 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);
}

递归

img

/**
 * 合并两有序链表  递归方法 代码少 但效率不行
 */
public ListNode mergeTwoLists(ListNode list1,ListNode list2){
    if(list1==null||list2==null){
        return list1==null?list2:list1;
    }else if(list1.val<list2.val){
        list1.next=mergeTwoLists(list1.next,list2);
        return list1;
    }else{
        list2.next=mergeTwoLists(list2.next,list1);
        return list2;
    }
}
/**
 * 普通方法 代码多 但效率快
 */
/*
public ListNode mergeTwoLists(ListNode list1,ListNode list2){
    if(list1==null||list2==null){
        return list1==null?list2:list1;
    }
    ListNode head=new ListNode(0);
    ListNode tail=head,aptr=list1,bptr=list2;
    while (list1!=null&&list2!=null){
        if(list1.val<list2.val){
            tail.next=list1;
            list1=list1.next;
        }else{
            tail.next=list2;
            list2=list2.next;
        }
        tail=tail.next;
    }
    tail.next=list1!=null?list1:list2;
    return head.next;
}
 */

数学、规律

通项公式

image-20220529175511733 image-20220529175454488

力扣48题翻转矩阵

image-20220516212619082 image-20220516212931381

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

//        官方第二种方法
        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进行插件更新!这是没想到的!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要在VS Code上力扣LeetCode)题目,首先需要进行以下几步操作: 1. 安装VS Code插件:在VS Code搜索并安装LeetCode插件。这个插件可以提供LeetCode题目的在线编写和提交功能,以及自动测试和调试代码的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [【史上最强代码编辑器VS Code】之VS Code力扣LeetCode)题目](https://blog.csdn.net/weixin_44553006/article/details/105183522)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [在 vscode 上力扣 Leetcode 可以这样来](https://blog.csdn.net/u012190388/article/details/121277555)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [leetcode答案-algo-study:从零开始力扣(LeetCode),JavaScript语言,算法](https://download.csdn.net/download/weixin_38680764/19920528)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值