剑指 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&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
- ^:异或
计算方式:符号左右两边的二进制数,相应的位相同为0,不相同为1。
举例:
十进制 8, 转换二进制为 1000
十进制10,转换二进制为1010
那么,1000^1010 = 0010
- <<逻辑左移
例如:
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