剑指 Offer 03. 数组中重复的数字(简单)
思路:set集合的add和contains
存在问题:页面做题没有自动补全,对库函数操作忘记,==set.contains()== , ==set.add()== , ==HashSet<Integer> set = new HashSet<>()==
class Solution {
public int findRepeatNumber(int[] nums) {
HashSet<Integer> set = new HashSet<>();
for(int i=0;i<nums.length;i++){
if(set.contains(nums[i])){
return nums[i];
}
set.add(nums[i]);
}
return 0;
}
}
剑指 Offer 04. 二维数组中的查找(中等)
思路:先按列找再按行找,主要逆序找会避免很多判定操作
存在问题:一开始顺序找的,代码非常复杂,后来看了题解才去逆序找
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
if(matrix==null||matrix.length==0)return false;
for(int i=0;i<matrix.length;i++){
int j=matrix[i].length-1;
if(j<0)continue;
while(j>0&&matrix[i][j]>target)j--;
if(matrix[i][j]==target)return true;
}
return false;
}
}
剑指 Offer 05. 替换空格(简单)
思路:遍历替换
存在问题:Java里面遍历字符串不像C++可以下标操作,需要==s.charAt(i)==,并且注意==字符用单引号==,==String的length带括号==,数组的length不带括号。
class Solution {
public String replaceSpace(String s) {
String res = new String();
for(int i=0;i<s.length();i++){
if(s.charAt(i)==' '){
res+="%20";
}
else{
res+=s.charAt(i);
}
}
return res;
}
}
剑指 Offer 06. 从尾到头打印链表(简单)
思路:遍历用栈逆置
存在问题:==访问栈顶用stack.peek()==,不是top()
class Solution {
public int[] reversePrint(ListNode head) {
Stack<Integer> sta = new Stack<>();
while(head!=null){
sta.push(head.val);
head = head.next;
}
int arr[] = new int[sta.size()];
int i=0;
while(!sta.isEmpty()){
arr[i++] = sta.peek();
sta.pop();
}
return arr;
}
}
剑指 Offer 07. 重建二叉树(中等)
思路:经典前中建树
存在问题:无
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder==null||preorder.length==0)return null;
return build(preorder[0],0,preorder.length-1,0,inorder.length-1,preorder,inorder);
}
public TreeNode build(int root,int prel,int prer,int inl,int inr,int[] preorder,int[] inorder){
TreeNode r = new TreeNode(root);
int countL = 0;
for(int i=inl;i<=inr;i++){
if(inorder[i]==root){
countL = i-inl;
break;
}
}
int countR = prer - prel - countL;
if(countL>0)r.left = build(preorder[prel+1],prel+1,prel+countL,inl,inl+countL,preorder,inorder);
else r.left = null;
if(countR>0)r.right=build(preorder[prel+1+countL],prel+1+countL,prer,inl+countL+1,inr,preorder,inorder);
else r.right = null;
return r;
}
}
剑指 Offer 14- I. 剪绳子(中等)
思路:一开始不知道结论,就模拟减成2~m-1段去比较最大值,第一题数据弱故可以过
存在问题:无
class Solution {
public int cuttingRope(int n) {
int max = 1;
for(int m=2;m<n;m++){
int k[] = new int[m];
for(int i=0;i<m;i++){
k[i]=n/m;
}
for(int i=0;i<n%m;i++){
k[i]++;
}
int r = 1;
for(int i=0;i<m;i++){
r *= k[i];
}
if(r>max)max=r;
}
return max;
}
}
剑指 Offer 14- II. 剪绳子 II(中等)
思路:本体需要先得出数学结论,利用结论直接算结果:
长度为n,分成m段,我们先假设是平均分,每段长度为l则有n = m*l
我们想求解最佳均分长度l 设,l为x,总长度为k, 则要分成 k/x段 ,其总乘积为
对这个式子进行求导,结果为:
显然,当x等于自然底数e(2.71828)的时候,导数为0,取最大值,2.718282介于2和3之间,通过分别带入2和3进入式子计算,发现以3为长度切段为最佳,并且有余数时:
m%3 = 1 时:最优为将长度1分配到其中一段变成 3^(m-1)*4
m%3 = 2 时:由于f(x)*3*3*2 大于f(x)*4*4,所以剩余两个长度单独成段。
存在问题:一开始一直用int,中间有样例错的离谱,一直不知道怎么回事,后来看到样例数据大小长度接近9位才意识到要用Long
class Solution {
public int cuttingRope(int n) {
long res = 1;
int p = 1000000007;
if(n<=3){
return n-1;
}
if(n%3==1){
res = 4;
n-=4;
}
else if(n%3==2&&n!=2) {
res = 2;
n-=2;
}
for(int i=0;i<n/3;i++){
res = res*3%p;
}
return (int)res;
}
}
2279. 装满石头的背包的最大数量(中等)
思路: 贪心,计算背包剩余空间然后排序一下,模拟装填,看看最多能装多少。
存在问题:一开始不知道Java里面快排怎么用:==Arrays.sort(difference)==,并且注意,如果使用逆序排序器的话,必须声明Integer的数组。后面会有例子。
class Solution {
public int maximumBags(int[] capacity, int[] rocks, int additionalRocks) {
int difference[] = new int[capacity.length];
for(int i=0;i<capacity.length;i++){
difference[i]=capacity[i]-rocks[i];
}
Arrays.sort(difference);
int count=0;
int i=0;
for(;i<difference.length&&difference[i]==0;i++,count++);
while(additionalRocks>0&&i<difference.length){
if(additionalRocks>=difference[i]){
additionalRocks-=difference[i++];
count++;
}
else break;
}
return count;
}
}
2551. 将珠子放入背包中(困难)
思路:因为必须是连续放珠子,所以将相当于静态分组。小学的时候老师讲过一句话,分组就相当于在队列里插挡板,分成n组就插n-1个挡板。这句话在这里及其好用,而且只需要维护挡板两侧数之和就可以。用一个长度n-1的数组计算一下原数组两两相邻数的和,然后分别排个序,顺序取k-1个就是最小值,逆序取k-1个就是。注意这里可以只排序一遍就行了,我为了学一下逆序怎么排所以排了两遍。
存在问题:又存在Long的问题,不过这次还好,看到他题干函数返回值给的Long就意识到了。还有逆序排序器的使用:==Arrays.sort(arr,Collections.reverseOrder());==
class Solution {
public long putMarbles(int[] weights, int k) {
if(weights.length<=k)return 0;
Long arr[] = new Long[weights.length-1];
for(int i=0;i<arr.length;i++){
arr[i]=(long)weights[i]+weights[i+1];
}
Long max=0L;
Long min=0L;
Arrays.sort(arr);
for(int i=0;i<k-1;i++){
min+=arr[i];
}
Arrays.sort(arr,Collections.reverseOrder());
for(int i=0;i<k-1;i++){
max+=arr[i];
}
return max-min;
}
}
1812. 判断国际象棋棋盘中一个格子的颜色(简单)
思路:无聊,当时好像在搜动态规划的分类,想先做个简单题看看,结果来个这个,可以说分类很不准确。
问题:无
class Solution {
public boolean squareIsWhite(String coordinates) {
HashMap<Character, Integer> map = new HashMap();
map.put('a',1);
map.put('b',2);
map.put('c',3);
map.put('d',4);
map.put('e',5);
map.put('f',6);
map.put('g',7);
map.put('h',8);
if((map.get(coordinates.charAt(0))+(int)coordinates.charAt(1))%2==1)return true;
else return false;
}
}
17. 电话号码的字母组合
思路:本来已经在打游戏了,女票问:你有没有做过回溯的题目,我一听名字很陌生,不过回溯这个名次在搜索里面听过,果然,搜索回溯,把返回的结果回溯稍微合并一下继续向上返回。
存在问题:不熟悉char转int的操作,直接强转结果得到了ASCII爆了空指针。
class Solution {
public List<String> letterCombinations(String digits) {
HashMap<Integer,String> hashMap = new HashMap();
hashMap.put(2,"abc");
hashMap.put(3,"def");
hashMap.put(4,"ghi");
hashMap.put(5,"jkl");
hashMap.put(6,"mno");
hashMap.put(7,"pqrs");
hashMap.put(8,"tuv");
hashMap.put(9,"wxyz");
if(digits==null||digits.length()==0)return new ArrayList<>();
return dfs("",0,digits,hashMap);
}
public List<String> dfs(String res, int it,String digits,HashMap<Integer,String> hashMap){
List<String>list = new ArrayList<>();
if(it>=digits.length()){
list.add(res);
return list;
}
int num = (int)(digits.charAt(it)-'0');
String des = hashMap.get(num);
for(int i=0;i<des.length();i++){
char c = des.charAt(i);
List<String>curr = dfs(res+c,it+1,digits,hashMap);
for(int j=0;j<curr.size();j++){
list.add(curr.get(j));
}
}
return list;
}
}