【lc刷题 day10】两个链表的第一个公共节点 在排序数组中查找数字 0~n-1中缺失的数字 二叉搜索树的第k大节点...

剑指 Offer 52. 两个链表的第一个公共节点 easy

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
class Solution {
    ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        ListNode node1=headA,node2=headB;
        while(node1!=node2){
            node1=node1==null?headB:node1.next;
            node2=node2==null?headA:node2.next;
        }
        return node1;
    }
}

时间复杂度O(M+N),空间复杂度O(1)

剑指 Offer 53 - I. 在排序数组中查找数字 I easy

class Solution {
    public int search(int[] nums, int target) {
        if(nums==null||nums.length==0) return 0;
        int left=0,right=nums.length-1;
        while(left<=right){
            int mid=(left+right)/2;
            if(nums[mid]==target){
                int l=mid,r=mid;
                while(l-1>=0&&nums[l-1]==target){
                    l--;
                }
                while(r+1<nums.length&&nums[r+1]==target){
                    r++;
                }
                return r-l+1;
            }else if(nums[mid]<target){
                left=mid+1;
            }else{
                right=mid-1;
            }
        }
        return 0;
    }
}

二分法
时间复杂度O(log2N),空间复杂度O(1)

剑指 Offer 53 - II. 0~n-1中缺失的数字 easy

class Solution {
    public int missingNumber(int[] nums) {
        int i = 0, j = nums.length - 1;
        while(i <= j) {
            int m = (i + j) / 2;
            if(nums[m] == m) i = m + 1;
            else j = m - 1;
        }
        return i;
    }
}

看这位大神的题解
https://leetcode.cn/problems/que-shi-de-shu-zi-lcof/solutions/155915/mian-shi-ti-53-ii-0n-1zhong-que-shi-de-shu-zi-er-f/

剑指 Offer 54. 二叉搜索树的第k大节点

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int count,res;
    public int kthLargest(TreeNode root, int k) {
        count=k;
        inorder(root);
        return res;
    }
    void inorder(TreeNode root){
        if(root==null) return;
        inorder(root.right);
        if(count==1) res=root.val;
        count--;
        inorder(root.left);
    }
}

剑指 Offer 55 - I. 二叉树的深度 easy

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        return root==null?0:Math.max(maxDepth(root.left),maxDepth(root.right))+1;
    }
}

只有一行代码,但是还挺难想的

剑指 Offer 55 - II. 平衡二叉树 easy

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isBalanced(TreeNode root) {
        if(root==null) return true;
        return Math.abs(maxDepth(root.left)-maxDepth(root.right))<=1&&isBalanced(root.left)&&isBalanced(root.right);
    }
    int maxDepth(TreeNode node){
        return node==null?0:Math.max(maxDepth(node.left),maxDepth(node.right))+1;
    }
}

要用到上面那道题的思路
java中求绝对值为Math.abs(x)

剑指 Offer 56 - I. 数组中数字出现的次数 medium

class Solution {
    public int[] singleNumbers(int[] nums) {
        int x = 0, y = 0, n = 0, m = 1;
        for(int num : nums)               // 1. 遍历异或
            n ^= num;
        while((n & m) == 0)               // 2. 循环左移,计算 m
            m <<= 1;
        for(int num: nums) {              // 3. 遍历 nums 分组
            if((num & m) != 0) x ^= num;  // 4. 当 num & m != 0
            else y ^= num;                // 4. 当 num & m == 0
        }
        return new int[] {x, y};          // 5. 返回出现一次的数字
    }

要做出这道题要先了解java中的几个运算符

  1. &:按位与

1&1=1 1&0=0 0&0=0
//12 转为二进制 0000 1100
//5 转为二进制 0000 0101
//1为真,0为假,按逻辑,只有前后都为真,结果才为真 也就是只有在 1&1 时,结果才为1 ,其他情况结果都是0
// 所以返回结果是
0000 0100,转为10进制数就是4
System.out.println(12 & 5);//4

  1. ^:异或

计算方式:符号左右两边的二进制数,相应的位相同为0,不相同为1。

举例:

十进制 8, 转换二进制为 1000

十进制10,转换二进制为1010

那么,1000^1010 = 0010

  1. <<逻辑左移

例如:

3<<1

是将3先转化为24位的二进制

0000 0000 0000 0000 0000 0000 0000 0011

然后再左移一位 最后结果为 0000 0000 0000 0000 0000 0000 0000 0110

再转化为十进制结果为6

如果左移过程中超过了32位 高位就会舍弃 低位补零

>>是右移 和<<具有同样的道理

只不过右移过程中溢出时,低位会舍弃,高位补零

设nums为{a1,a1,a2,a2,…,an,an,x,y}
这道题的思路是现将数组中所有数字异或,由于相同数字异或结果为0,所以最后的结果一定是想x^y
由于x与y不同,所以只有有一位异或结果为1
找到异或为1的那个数字,将nums数组分为两组
两组再分别异或,异或结果即为x与y
满足题目要求:
时间复杂度O(N),空间复杂度O(1)

剑指 Offer 56 - II. 数组中数字出现的次数 II medium

class Solution {
    public int singleNumber(int[] nums) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int number : nums) 
            map.put(number, map.getOrDefault(number, 0) + 1);
        for (int number : map.keySet()) 
            if (map.get(number) == 1) 
                return number;
        return 0;
    }
}

这道题是有更加优化的方法的,位运算具体可以看leetcode题解
感觉太难了,懒得看了
用的hashmap的方式,遍历列表的方式有必要学习一下

//遍历hashmap的方式
for (int number : map.keySet()) 

剑指 Offer 57. 和为s的两个数字 easy

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int left=0,right=nums.length-1;
        Arrays.sort(nums);
        while(left<right){
            if(nums[left]+nums[right]==target){
                return new int[]{nums[left],nums[right]};
            }else if(nums[left]+nums[right]>target){
                right--;
            }else{
                left++;
            }
        }
        return new int[0];
    }
}

用双指针的方法比较好
时间复杂度O(N),空间复杂度O(1)

剑指 Offer 57 - II. 和为s的连续正数序列 easy

class Solution {
    public int[][] findContinuousSequence(int target) {
        List<int[]> list=new ArrayList<>();
        int left=1,right=2,sum=3;
        while(left<right&&left<=target/2){
            if(sum==target){
                int cnt=right-left+1;
                int[] res=new int[cnt];
                int i=0;
                for(int k=left;k<=right;k++){
                    res[i++]=k;
                }
                list.add(res);
            }
            if(sum>=target){
                sum-=left;
                left++;
            }else{
                right++;
                sum+=right;
            }
        }
        int[][] arrs=new int[list.size()][];
        int i=0;
        for(int[] arr:list){
            arrs[i++]=arr;
        }
        return arrs;
    }
}

我觉得这道题难度不像是简单题,希望做一遍能记住
双指针,从left=1,right=2,sum=1+2=3开始试
while循环的条件是left<right&&left<=target/2
如果sum==target,则将结果写入列表
如果sum>=target,sum-=left; left++注意这里需要加‘=’是因为可能存在多组结果,比如15可以由1,2,3,4,5组成,也可由7,8组成
如果sum<target,right++,sum+=right
时间复杂度O(n),空间复杂度O(1)

剑指 Offer 58 - I. 翻转单词顺序 easy

class Solution {
    public String reverseWords(String s) {
        s=s.trim();
        String[] strs=s.split(" ");
        String res="";
        for(int i=strs.length-1;i>=0;i--){
            if(strs[i]=="") continue;
            res+=strs[i];
            if(i!=0){
                res+=" ";
            }
        }
        return res;
    }
}

这道题一个是学习String.split方法
还有一个是要注意这一行
if(strs[i]==“”) continue;
如果不加的话,如果有连续3个“ ”,就会出现strs[i]为“”

剑指 Offer 58 - II. 左旋转字符串 easy

class Solution {
    public String reverseLeftWords(String s, int n) {
        String s1=s.substring(0,n);
        String s2=s.substring(n);
        return s2+s1;
    }
}

感觉这些都不是高频题,刷了好没有意义啊

剑指 Offer 60. n个骰子的点数 medium

class Solution {
    public double[] dicesProbability(int n) {
        double[] dp=new double[6];
        for(int i=0;i<6;i++){
            dp[i]=1.0/6.0;
        }
        for(int i=2;i<=n;i++){
            double[] tmp=new double[5*i+1];
            for(int j=0;j<dp.length;j++){
                for(int k=0;k<6;k++){
                    tmp[j+k]+=dp[j]*(1.0/6.0);
                }
            }
            dp=tmp;
        }
        return dp;
    }
}

这道题还是得去看题解,用的动态规划

剑指 Offer 62. 圆圈中最后剩下的数字 easy

class Solution {
    public int lastRemaining(int n, int m) {
        List<Integer> list=new ArrayList<>();
        for(int i=0;i<n;i++){
            list.add(i);
        }
        int idx=0;
        while(n!=1){
            idx=(idx+m-1)%n;
            list.remove(idx);
            n--;
        }
        return list.get(0);
    }
}

今天一共写了14道题hhhh

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值