算法日记---新动计划
前言
LeetCode【新】动计划提单用于巩固基础语法,是新手小白入门的首选,此篇对一些题目进行解析和记录。
一、709. 转换成小写字母
给你一个字符串 s
,将该字符串中的大写字母转换成相同的小写字母,返回新的字符串。
本题重点在于如何将大写字母转换为小写字母:将大写字母的ASCII码加上小写字母和对应大写字母在ASCII码上的差值(32)即获得小写字母
1.创建StringBuilder对象result,用于高效拼接字符串的类,若使用普通的String进行拼接,每次拼接都会生成一个新的String对象,效率较低,而StringBuilder可以在原有对象基础上进行修改,提高效率。
2.for(char c:s.toCharArray())使用增强for循环遍历字符串s转换为字符数组后的每个字符,s.toCharArray()方法将字符串s转换为一个字符数组,这样就可以逐个获取字符串中的字符了。
3.
4.将处理后的字符c无论是原本的小写字母、非字母字符还是转换后的小写字母。全部通过append方法添加到StringBuilder对象result中
5.将StringBuilder对象result转换为String类型并返回。
class Solution {public String toLowerCase(String s) {StringBuilder result=new StringBuilder();for(char c:s.toCharArray()){if (c >= 'A' && c <= 'Z') {c = (char) (c + ('a' - 'A'));}result.append(c);}return result.toString();
}
}
二、258. 各位相加
1.第一种方法:模拟各位相加的过程:超时
- 外层
while
循环判断num
是否大于等于 10,如果是,说明还需要继续各位相加。 - 内层
while
循环用于计算当前num
各位数字的和,通过取余(num % 10
)得到个位数字,累加到sum
中,然后通过整除(num /= 10
)去掉个位数字,直到num
变为 0。 - 最后将
sum
赋值给num
,继续外层循环判断,直到num
是一位数,返回num
。
2.
进阶:你可以不使用循环或者递归,在 O(1)
时间复杂度内解决这个问题吗?
以下为灵神的题解
class Solution {public int addDigits(int num) {return (num - 1) % 9 + 1;}
}
如果无法总结出公式,进行if判断,结果也是一样的。
class Solution {public int addDigits(int num) {if (num == 0) {return 0;}int remainder = num % 9;return remainder == 0 ? 9 : remainder;}
}
三、231. 2 的幂
给你一个整数 n
,请你判断该整数是否是 2 的幂次方。如果是,返回 true
;否则,返回 false
。
如果存在一个整数 x
使得 n == 2x
,则认为 n
是 2 的幂次方。
以下是使用位运算进行解答,时间复杂度O(1)
class Solution {public boolean isPowerOfTwo(int n) {return n>0 && (n&(n-1))==0;}
}
当然也可以使用循环或递归,时间复杂度为O(log n)
class Solution {public boolean isPowerOfTwo(int n) {if (n <= 0) return false;while (n % 2 == 0) {n /= 2;}return n == 1;}
}
class Solution {public boolean isPowerOfTwo(int n) {if (n <= 0) return false;if (n == 1) return true;if (n % 2 != 0) return false;return isPowerOfTwo(n / 2);}
}
通过递归逐步将数字减半,检查最终是否能得到 1。
更多位运算技巧,可参考灵神的《 从集合论到位运算,常见位运算技巧分类总结!》
四、867. 转置矩阵
class Solution {public int[][] transpose(int[][] matrix) {int n=matrix.length;int m=matrix[0].length;int[][] ans=new int[m][n];for(int i=0;i<n;i++){for(int j=0;j<m;j++){ans[j][i]=matrix[i][j];}}return ans;}
}
五、1470. 重新排列数组
class Solution {public int[] shuffle(int[] nums, int n) {int[] ans=new int[2*n];for(int i=0;i<n;i++){ans[2*i]=nums[i];ans[2*i+1]=nums[i+n];}return ans;}
}
六、1422. 分割字符串的最大得分
class Solution {public int maxScore(String s) {int ans=0;int n=s.length();for(int i=1;i<n;i++){int score=0;for(int j=0;j<i;j++){if(s.charAt(j)=='0'){score++;}}for(int j=i;j<n;j++){if(s.charAt(j)=='1'){score++;}}ans=Math.max(ans,score);}return ans;}
}
七、852. 山脉数组的峰顶索引
这题依旧是二分,虽然有点不一样但本质还是不断缩小二分的范围,最后确定,那么缩小的条件是什么呢?---arr[mid]>arr[mid+1]
我们的目标是通过二分查找,找到第一个满足 arr[mid] > arr[mid+1]
的位置(因为从该位置开始,数组进入「递减段」,而它本身就是峰值)。
二分过程中,left
和 right
的移动规则是:
- 如果
arr[mid] > arr[mid+1]
:说明mid
可能在「递减段」,峰值可能在mid
或mid
左侧,因此调整right = mid - 1
,尝试在左半段继续查找。 - 如果
arr[mid] <= arr[mid+1]
:说明mid
在「递增段」,峰值一定在mid
右侧,因此调整left = mid + 1
,去右半段查找。
class Solution {public int peakIndexInMountainArray(int[] arr) {//因为答案一定在[1,n-2]中,所以初始化如下int left=1;int right=arr.length-2;while(left<=right){int mid=(left+right)>>>1;if(arr[mid]>arr[mid+1]){//二分右边界时,一定成立right=mid-1;}else{//二分左边界时,一定不成立left=mid+1;}}// 循环结束后,left 就是峰值元素的下标return left;}
}
总结
加油