半小时看完阿里大牛珍藏的纯手写“Kafka文档”,Leetcode每日一题(1)

if(cnt1 <= 0){

if(cnt2 < 0) return false;

else cnt2–;

}else cnt1–;

}else if(s[i] ==‘*’){

cnt2++;

}

}

printf(“%d\n”,cnt1);

printf(“%d\n”,cnt2);

if(cnt1 == 0 || cnt2 >= cnt1) return true;

return false;

}

};

使用双栈,栈内保存下标

其实第一次遍历和上面模拟思路是一样的,区别点在于

第二次遍历的时候,将*视为右括号,每个左括号必须在右括号之前

class Solution {

public:

bool checkValidString(string s) {

stack s1,s2;

for(int i = 0;s[i];i++){

if(s[i] == ‘(’) s1.push(i);

else if(s[i] == ‘)’){

if(!s1.empty()) s1.pop();

else {

if(!s2.empty()) s2.pop();

else return false;

}

}else s2.push(i);

}

while(!s1.empty() && !s2.empty()){

int idx1 = s1.top(),idx2 = s2.top();

s1.pop(),s2.pop();

if(idx1 > idx2) return false;

}

if(s1.empty()) return true;

return false;

}

};

贪心

维护最大值和最小值

  • 当遇到左括号,最大值和最小值都加一

  • 遇到右括号,最小值和最小值都减一

  • 遇到星号,最大值加一,最小值减一

维护时应该

  • 保证最小值非负

  • 判断最大值是否为负,如果为负,则返回

  • 最后判断最小值是否为0,为0则表示左右括号能匹配成功

class Solution {

public:

bool checkValidString(string s) {

int minn = 0,maxn = 0;

for(int i = 0;s[i];i++){

if(s[i] == ‘(’) minn++,maxn++;

else if(s[i] == ‘)’){

maxn–;

minn = max(0,minn-1);

if(maxn < 0) return false;

}else{

maxn++;

minn = max(0,minn-1);

}

}

return minn == 0;

}

};

2021.9.13


447. 回旋镖的数量
  • 距离使用平方,避免开方

  • 使用哈希表查找

  • 从m 个元素中选出 2 个不同元素的排列数

  • image-20210913115240805

class Solution {

public:

int numberOfBoomerangs(vector<vector>& points) {

if(points.size() <= 2) return 0;

int ans = 0;

for(int i = 0;i < points.size();i++){

unordered_map<int,int> m;

int x1 = points[i][0],y1 = points[i][1];

for(int j = 0;j < points.size();j++){

int x2 = points[j][0],y2 = points[j][1];

if(i == j) continue;

int dis = (x2-x1)(x2-x1) + (y2-y1)(y2-y1);

m[dis]++;

}

for(auto dis:m) ans += (dis.second-1) * dis.second;

}

return ans;

}

};

2021.9.14


524. 通过删除字母匹配到字典里最长单词
  1. 先对字典排序,排序后字典序是由大到小

  2. 双指针,判断字典里面的字符串的指针能否走完,能走完就是s字符串的子串

  3. 如果长度长那就替换,因为越到后面字典序越小

class Solution {

public:

string findLongestWord(string s, vector& dictionary) {

string ans = “”;

sort(dictionary.rbegin(),dictionary.rend());

for(int i = 0;i < dictionary.size();i++){

string sub = dictionary[i];

int k = 0;

for(int j = 0;j < s.size();j++){

while(k < sub.size() && sub[k] == s[j]) k++,j++;

}

if(k == sub.size() && sub.size() >= ans.size()) ans = sub;

}

return ans;

}

};

image-20210914102637657

2021.9.15


162. 寻找峰值

遍历,处理好边界即可

法一:遍历

class Solution {

public:

int findPeakElement(vector& nums) {

if(nums.size() == 1) return 0;

for(int i = 0;i < nums.size();i++){

if(i == 0) {

if(nums[0] > nums[1]) return 0;

}

else if(i == nums.size()-1) {

if(nums[nums.size()-1] > nums[nums.size()-2]) return nums.size()-1;

}

else {

if(nums[i] > nums[i-1] && nums[i] > nums[i+1]) return i;

}

}

return -1;

}

};

image-20210915100813919

法二:二分

class Solution {

public:

int findPeakElement(vector& nums) {

int l = 0,r = nums.size()-1;

while(l < r){

int mid = (l+r) >> 1;

if(nums[mid] > nums[mid+1]) r = mid;

else l = mid + 1;

}

return l;

}

};

思考一下:

  • 因为num[i] != num[i+1],并且num[-1] = num[N] = 负无穷

  • 这就代表着 只要数组中存在一个元素比相邻元素大,那么沿着它一定可以找到一个峰值

  • 根据上述结论,我们就可以使用二分查找找到峰值

  • 查找时,左指针 l,右指针 r,以其保持左右顺序为循环条件

  • 根据左右指针计算中间位置 m,并比较 m 与 m+1 的值,如果 m 较大,则左侧存在峰值,r = m,如果 m + 1 较大,则右侧存在峰值,l = m + 1

  • Base on : https://leetcode-cn.com/problems/find-peak-element/solution/hua-jie-suan-fa-162-xun-zhao-feng-zhi-by-guanpengc/ 作者:guanpengchn

2021.9.17


36. 有效的数独

class Solution {

public:

bool isValidSudoku(vector<vector>& board) {

// 遍历每一行每一列

for(int i = 0;i < 9;i++){

int x[9],y[9];

for(int i = 0;i < 9;i++) x[i] = 0,y[i] = 0;

for(int j = 0;j < 9;j++){

int idxx = board[i][j] - ‘0’,idxy = board[j][i] - ‘0’;

if(idxx >=0 && idxx <= 9){

if(!x[idxx-1]) x[idxx-1] = 1;

else return false;

}

if(idxy >= 0 && idxy <= 9){

if(!y[idxy-1]) y[idxy-1] = 1;

else return false;

}

}

}

// 遍历九个方格

int count = 9;

int countx=-3,county=0;

while(count–){

countx+=3;

if(countx == 9) countx = 0,county+=3;

int st[9];

for(int i = 0;i < 9;i++) st[i] = 0;

for(int i = 0+county;i < 3+county;i++){

// 输出三行

for(int j = 0+countx;j < 3+countx;j++){

int idx = (int)(board[i][j] - ‘0’);

if(idx >= 1 && idx <= 9) {

if(!st[idx-1]) st[idx-1] = 1;

else return false;

}

}

}

}

return true;

}

};

image-20210917110601901

2021.9.19


650. 只有两个键的键盘

class Solution {

// 判断是否为指数

public boolean isPrime(int x){

if(x <= 2) return false;

for(int i = 2;i <= x/i;i++){

if(x%i==0) return false;

}

return true;

}

public int minSteps(int n) {

// dp[i],i这个数,最小的操作数

int[] dp = new int[n+1];

for(int i = 0;i <=n;i++){

// 质数

if(isPrime(i)) dp[i] = i;

// 偶数

else if(i%2 == 0) dp[i] = dp[i/2] + 2;

// 奇数

else {

for(int j = i-1;j > 0;j–){

if(i % j == 0){

dp[i] = dp[j] + i/j;

break;

}

}

}

}

return dp[n];

}

}

我觉得这个思路其实就相当DP了

2021.9.20


300. 最长递增子序列

class Solution {

public int lengthOfLIS(int[] nums) {

int n = nums.length,maxL = 0;

int[] dp = new int[n];

for(int i = 0;i < n;i++){

dp[i] = 1;

for(int j = 0;j < i;j++){

if(nums[i] > nums[j]){

if(dp[j] + 1 > dp[i]) dp[i] = dp[j]+1;

}

}

if(dp[i] > maxL) maxL = dp[i];

}

return maxL;

}

}

DP分析:

  • dp数组以及下表含义:

  • 以nums[i]结尾的元素的最长递增子序列的长度

  • dp的边界考虑

  • 每次遍历之前dp[i]初始化为1,当作一个数字作为上升子序列

  • dp的状态转移方程

  • dp[i] = max(dp[j]) + 1

  • 因为dp[j]表示第i个元素之前的最长递增子序列的长度,那么直接将num[i]插入最后面还能构成递增子序列的话就能求出dp[i]

  • 遍历顺序

  • j在i之前,dp[i]需要dp[j],从左往右

  • 打印dp表

image-20210920092535072

image-20210920092552040

673. 最长递增子序列的个数

class Solution {

public int findNumberOfLIS(int[] nums) {

int n = nums.length,maxL = 0,ans = 0;

// 以nums[i]结尾的最长上升子序列的长度

int[] dp = new int[n];

// 以nums[i]结尾的最长上升子序列的个数

int[] cnt = new int[n];

// 遍历

for(int i = 0;i < n;i++){

dp[i] = 1;

cnt[i] = 1;

for(int j = 0;j < i;j++){

// 可以直接加在dp[j]之后

if(nums[i] > nums[j]){

if(dp[j] + 1 > dp[i]){

// 能构成一个比之前长的递增子序列

dp[i] = dp[j]+1;

cnt[i] = cnt[j];

// 构成的上升子序列和之前的上升子序列一样长

}else if(dp[j] + 1 == dp[i]) cnt[i] += cnt[j];

}

}

// 刷新最大长度

if(dp[i] > maxL){

maxL = dp[i];

ans = cnt[i];

}else if(dp[i] == maxL) ans += cnt[i];

}

return ans;

}

}

DP分析的方法和上面一题一样,这里多了个cnt[]数组

cnt[i]表示以nums[i]结尾的最长上升子序列的个数

image-20210920092822834

2021.9.21


58. 最后一个单词的长度

class Solution {

public int lengthOfLastWord(String s) {

int ans = 0;

boolean flag = true;

for(int i = s.length()-1;i >=0;i–){

if(s.charAt(i) == ’ ’ && flag) continue;

else {

flag = false;

if(s.charAt(i) == ’ ') break;

ans++;

}

}

return ans;

}

}

从后面往前面遍历,从第一个不是空格的字母到第一个空格

image-20210921100432519

2021.9.22


2021.9.23


326. 3的幂

class Solution {

public boolean isPowerOfThree(int n) {

long x = 1;

while(x <= n){

if(x == n) return true;

x *= 3;

}

return false;

}

}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CPNXY67D-1634459055741)(https://i.loli.net/2021/09/23/hFNZm4jPOUqs9MT.png)]

2021.9.26


371. 两整数之和

class Solution {

public int getSum(int a, int b) {

int count = 1;

while(b != 0){

// a & b 可以得出所有需要进位的位

// << 1 将进位的位置移到需要进位的地方

int carry = (a&b) << 1;

// ^ 异或运算,无进位加法

a = a ^ b;

b = carry;

}

return a;

}

}

https://leetcode-cn.com/problems/sum-of-two-integers/solution/liang-zheng-shu-zhi-he-by-leetcode-solut-c1s3/

2021.10.1


1436. 旅行终点站

双重遍历:如果cityB没有在cityA出现过

class Solution {

public String destCity(List<List> paths) {

int n = paths.size();

for(int i = 0;i < n;i ++ ){

List list1 = paths.get(i);

String second = list1.get(1);

boolean flag = true;

for(int j = 0;j < n;j++){

List list2 = paths.get(j);

String first = list2.get(0);

if(first.equals(second)){

flag = false;

break;

}

}

if(flag) return second;

}

return null;

}

}

哈希表:

class Solution {

public String destCity(List<List> paths) {

Set hashSet = new HashSet<>();

// 遍历cityA

for(List list : paths){

String cityA = list.get(0);

hashSet.add(cityA);

}

// 遍历cityB,如果cityB没有在cityA出现过,那就是终点

for(List list : paths){

String cityB = list.get(1);

if(!hashSet.contains(cityB)) return cityB;

}

return null;

}

}

2021.10.2


405. 数字转换为十六进制数

进制转换-> 辗转相除法

class Solution {

public String toHex(int _num) {

if(_num == 0) return “0”;

Stack stack = new Stack<>();

String str = “0123456789abcdef”;

long num = _num;

if(num < 0) num = (long)(Math.pow(2, 32) + num);

int size = 0;

while(num > 0){

long k = num % 16;

stack.push(str.charAt((int)k));

num /= 16;

size++;

}

char[] ans = new char[size];

int idx = 0;

for(int i = 0;i < size;i++) ans[idx++] = stack.pop();

return new String(ans);

}

}

调用函数:

class Solution {

public String toHex(int num) {

return Integer.toHexString(num);

}

}

2021.10.3


166. 分数到小数

class Solution {

public String fractionToDecimal(int numerator, int denominator) {

// 转成long,防止溢出

long a = numerator,b = denominator;

// 如果自身能被整除,直接返回

if(a % b == 0) return String.valueOf(a / b);

StringBuilder sb = new StringBuilder();

// 如果有一个是负数,先追加负号

if(a * b < 0) sb.append(‘-’);

// 都先变为正数

a = Math.abs(a);b = Math.abs(b);

// 计算小数点前的数,并将余数赋值给a

sb.append(String.valueOf(a/b) + “.”);

a %= b;

Map<Long,Integer> map = new HashMap<>();

while(a != 0){

// 记录当前的余数所在位置,并且继续模拟除法

map.put(a,sb.length());

// 后面加0

a*=10;

sb.append(a/b);

// 余数

a %= b;

// 如果当前余数之前出现过,则将 [出现位置 到 当前位置] 的部分抠出来(循环小数部分)

if(map.containsKey(a)){

int u = map.get(a);

return String.format(“%s(%s)”,sb.substring(0,u),sb.substring(u));

}

}

// 有限小数

return sb.toString();

}

}

思路来源:https://leetcode-cn.com/problems/fraction-to-recurring-decimal/solution/gong-shui-san-xie-mo-ni-shu-shi-ji-suan-kq8c4/

2021.10.4


482. 密钥格式化

两个char数组

class Solution {

public String licenseKeyFormatting(String s, int k) {

int n = s.length();

char[] ch = new char[n];

int len = 0;

for(int i = 0;i < n;i++){

if(s.charAt(i) != ‘-’) ch[len++] = Character.toUpperCase(s.charAt(i));

}

int cout = 0;

if(len%k == 0)cout = len/k-1;

else cout = len/k;

if(len + cout == -1) cout = 0;

char[] ans = new char[len+cout];

int idx = len+cout-1,k2 = k;

for(int i = len-1;i >= 0;i–){

if(idx >= 0)ans[idx–] = ch[i];

k2–;

if(k2 == 0 && idx >= 0) {

ans[idx–] = ‘-’;

k2 = k;

}

}

return new String(ans);

}

}

StringBuilder

class Solution {

public String licenseKeyFormatting(String s, int k) {

StringBuilder sb = new StringBuilder();

// 从后往前

for(int i = s.length()-1,cnt = 0;i >=0 ;i–){

if(s.charAt(i) == ‘-’) continue;

// 计数器

if(cnt == k){

sb.append(‘-’);

cnt = 0;

}

sb.append(s.charAt(i));

cnt++;

}

return sb.reverse().toString().toUpperCase();

}

}

2021.10.5


284. 顶端迭代器

// Java Iterator interface reference:

// https://docs.oracle.com/javase/8/docs/api/java/util/Iterator.html

class PeekingIterator implements Iterator {

// 迭代器

private Iterator iterator;

private Integer nextElement;

public PeekingIterator(Iterator iterator) {

// initialize any member here.

this.iterator = iterator;

nextElement = iterator.next();

}

// Returns the next element in the iteration without advancing the iterator.

public Integer peek() {

return nextElement;

}

// hasNext() and next() should behave the same as in the Iterator interface.

// Override them if needed.

@Override

public Integer next() {

Integer ret = nextElement;

nextElement = iterator.hasNext() ? iterator.next() : null;

return ret;

}

@Override

public boolean hasNext() {

return nextElement != null;

}

}

2021.10.6


414. 第三大的数

有序序列:

  • TreeSet里面就放最大的三个元素

  • 每次都把当前元素加进来,有重复的TreeSet自动去重

  • 当大于三个的时候,把最小的,就是第一个清除即可

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

学习分享,共勉

这里是小编拿到的学习资源,其中包括“中高级Java开发面试高频考点题笔记300道.pdf”和“Java核心知识体系笔记.pdf”文件分享,内容丰富,囊括了JVM、锁、并发、Java反射、Spring原理、微服务、Zookeeper、数据库、数据结构等大量知识点。同时还有Java进阶学习的知识笔记脑图(内含大量学习笔记)!

资料整理不易,读者朋友可以转发分享下!

Java核心知识体系笔记.pdf

记一次蚂蚁金服Java研发岗的面试经历,分享下我的复习笔记面经

中高级Java开发面试高频考点题笔记300道.pdf

记一次蚂蚁金服Java研发岗的面试经历,分享下我的复习笔记面经

架构进阶面试专题及架构学习笔记脑图

记一次蚂蚁金服Java研发岗的面试经历,分享下我的复习笔记面经

Java架构进阶学习视频分享
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

2021.10.6


414. 第三大的数

有序序列:

  • TreeSet里面就放最大的三个元素

  • 每次都把当前元素加进来,有重复的TreeSet自动去重

  • 当大于三个的时候,把最小的,就是第一个清除即可

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。[外链图片转存中…(img-6atQZUGY-1713466360448)]

[外链图片转存中…(img-aiuhyC33-1713466360448)]

[外链图片转存中…(img-47RIuESt-1713466360449)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

学习分享,共勉

这里是小编拿到的学习资源,其中包括“中高级Java开发面试高频考点题笔记300道.pdf”和“Java核心知识体系笔记.pdf”文件分享,内容丰富,囊括了JVM、锁、并发、Java反射、Spring原理、微服务、Zookeeper、数据库、数据结构等大量知识点。同时还有Java进阶学习的知识笔记脑图(内含大量学习笔记)!

资料整理不易,读者朋友可以转发分享下!

Java核心知识体系笔记.pdf

[外链图片转存中…(img-tNaVfHBy-1713466360449)]

中高级Java开发面试高频考点题笔记300道.pdf

[外链图片转存中…(img-4NaYllzo-1713466360449)]

架构进阶面试专题及架构学习笔记脑图

[外链图片转存中…(img-86p9DOdc-1713466360449)]

Java架构进阶学习视频分享
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 25
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值