剑指 Offer II 001. 整数除法

给定两个整数 a 和 b ,求它们的除法的商 a/b ,要求不得使用乘号 '*'、除号 '/' 以及求余符号 '%' 。

注意:

整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2

假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231−1]。本题中,如果除法结果溢出,则返回 231 − 1


示例 1:

输入:a = 15, b = 2

输出:7

解释:15/2 = truncate(7.5) = 7

示例 2:

输入:a = 7, b = -3

输出:-2

解释:7/-3 = truncate(-2.33333..) = -2

示例 3:

输入:a = 0, b = 1

输出:0

示例 4:

输入:a = 1, b = 1

输出:1


提示:

-231 <= a, b <= 231 - 1

b != 0

同 29. 两数相除​

class Solution:
def divide(self, a: int, b: int) -> int:
c = int(a/b)
if c > 2**31-1:
c = 2**31-1
return c

剑指 Offer II 002. 二进制加法

给定两个 01 字符串 a 和 b ,请计算它们的和,并以二进制字符串的形式输出。

输入为 非空 字符串且只包含数字 1 和 0。

示例 1:

输入: a = "11", b = "10"

输出: "101"

示例 2:

输入: a = "1010", b = "1011"

输出: "10101"


提示:

每个字符串仅由字符 '0' 或 '1' 组成。

1 <= a.length, b.length <= 10^4

字符串如果不是 "0" ,就都不含前导零。

def intToStrTmp(a,p):
if a == 0:
return ''
xend = a%p
a = a//p
return intToStrTmp(a,p) + str(xend)
def intToStr(a,p):
if a == 0:
return '0'
return intToStrTmp(a,p)
def strToInt(a,p):
if a == '':
return 0
xend = int(a[-1])
a = a[:-1]
return strToInt(a,p)*p + xend

class Solution:
def addBinary(self, a: str, b: str) -> str:
s = strToInt(a,2) + strToInt(b,2)
return intToStr(s, 2)

剑指 Offer II 003. 前 n 个数字二进制中 1 的个数

338. 比特位计数 ​​​

剑指 Offer II 004. 只出现一次的数字 

137. 只出现一次的数字 II​

剑指 Offer II 005. 单词长度的最大乘积

给定一个字符串数组 words,请计算当两个字符串 words[i] 和 words[j] 不包含相同字符时,它们长度的乘积的最大值。假设字符串中只包含英语的小写字母。如果没有不包含相同字符的一对字符串,返回 0。

示例 1:

输入: words = ["abcw","baz","foo","bar","fxyz","abcdef"]

输出: 16 

解释: 这两个单词为 "abcw", "fxyz"。它们不包含相同字符,且长度的乘积最大。

示例 2:

输入: words = ["a","ab","abc","d","cd","bcd","abcd"]

输出: 4 

解释: 这两个单词为 "ab", "cd"。

示例 3:

输入: words = ["a","aa","aaa","aaaa"]

输出: 0 

解释: 不存在这样的两个单词。


提示:

2 <= words.length <= 1000

1 <= words[i].length <= 1000

words[i] 仅包含小写字母

def bitFlag(s):
ans = 0
for i in range(len(s)):
n = ord(s[i]) - ord('a')
ans = ans | 1<<n
return ans

class Solution:
def maxProduct(self, words: List[str]) -> int:
b = []
for wi in words:
b.append(bitFlag(wi))
ans = 0
for i in range(len(words)):
for j in range (len(words)):
if i<j and b[i]&b[j]==0:
ans = max(ans,len(words[i])*len(words[j]))
return ans

剑指 Offer II 006. 排序数组中两个数字之和

本题与主站 167 题相似(下标起点不同)​

只需要把fjia(res,1);这一行删掉即可

剑指 Offer II 007. 数组中和为 0 的三个数

15. 三数之和 ​​​

剑指 Offer II 008. 和大于等于 target 的最短子数组

209. 长度最小的子数组 ​​​

剑指 Offer II 009. 乘积小于 K 的子数组

给定一个正整数数组 nums和整数 k ,请找出该数组内乘积小于 k 的连续的子数组的个数。

示例 1:

输入: nums = [10,5,2,6], k = 100

输出: 8

解释: 8 个乘积小于 100 的子数组分别为: [10], [5], [2], [6], [10,5], [5,2], [2,6], [5,2,6]。

需要注意的是 [10,5,2] 并不是乘积小于100的子数组。

示例 2:

输入: nums = [1,2,3], k = 0

输出: 0


提示: 

1 <= nums.length <= 3 * 104

1 <= nums[i] <= 1000

0 <= k <= 106

class Solution:
def numSubarrayProductLessThanK(self, nums: List[int], k: int) -> int:
if k <= 0:
return 0
s = e = 0
p = nums[0]
ans = 0
while s < len(nums):
while e < len(nums) and p < k:
e += 1
if e < len(nums):
p *= nums[e]
ans += max(e-s, 0)
p = p // nums[s]
s += 1
return ans

剑指 Offer II 010. 和为 k 的子数组

给定一个整数数组和一个整数 k ,请找到该数组中和为 k 的连续子数组的个数。

示例 1 :

输入:nums = [1,1,1], k = 2

输出: 2

解释: 此题 [1,1] 与 [1,1] 为两种不同的情况

示例 2 :

输入:nums = [1,2,3], k = 3

输出: 2


提示:

1 <= nums.length <= 2 * 104

-1000 <= nums[i] <= 1000

-107 <= k <= 107

class Solution {
public:
int subarraySum(vector<int>& nums, int k) {
for(int i=1;i<nums.size();i++)nums[i]+=nums[i-1];
nums.insert(nums.begin(),0);
int ans = 0;
map<int,int>m;
for(int i=0;i<nums.size();i++){
m[nums[i]]++;
}
for(int i=0;i<nums.size();i++){
m[nums[i]]--;
ans+=m[nums[i]+k];
}
return ans;
}
};

剑指 Offer II 011. 0 和 1 个数相同的子数组

给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最长连续子数组,并返回该子数组的长度。

示例 1:

输入: nums = [0,1]

输出: 2

说明: [0, 1] 是具有相同数量 0 和 1 的最长连续子数组。

示例 2:

输入: nums = [0,1,0]

输出: 2

说明: [0, 1] (或 [1, 0]) 是具有相同数量 0 和 1 的最长连续子数组。


提示:

1 <= nums.length <= 105

nums[i] 不是 0 就是 1

class Solution:
def findMaxLength(self, nums: List[int]) -> int:
x = 0
dict= {0:-1}
ans = 0
for i in range(0,len(nums)):
if nums[i]==0:
x += 1
else :
x -= 1
if dict.get(x, 1234567) == 1234567:
dict[x] = i
if ans < i - dict[x]:
ans = i - dict[x]
return ans

剑指 Offer II 012. 左右两边子数组的和相等

给你一个整数数组 nums ,请计算数组的 中心下标 。

数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。

如果中心下标位于数组最左端,那么左侧数之和视为 0 ,因为在下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。

如果数组有多个中心下标,应该返回 最靠近左边 的那一个。如果数组不存在中心下标,返回 -1 。

示例 1:

输入:nums = [1,7,3,6,5,6]

输出:3

解释:

中心下标是 3 。

左侧数之和 sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11 ,

右侧数之和 sum = nums[4] + nums[5] = 5 + 6 = 11 ,二者相等。

示例 2:

输入:nums = [1, 2, 3]

输出:-1

解释:

数组中不存在满足此条件的中心下标。

示例 3:

输入:nums = [2, 1, -1]

输出:0

解释:

中心下标是 0 。

左侧数之和 sum = 0 ,(下标 0 左侧不存在元素),

右侧数之和 sum = nums[1] + nums[2] = 1 + -1 = 0 。


提示:

1 <= nums.length <= 104

-1000 <= nums[i] <= 1000


class Solution:
def pivotIndex(self, nums: List[int]) -> int:
s = 0
for i in range(0,len(nums)):
s += nums[i]
s2 = 0
for i in range(0,len(nums)):
if s2 + s2 + nums[i] == s:
return i
s2 += nums[i]
return -1

剑指 Offer II 013. 二维子矩阵的和

给定一个二维矩阵 matrix,以下类型的多个请求:

计算其子矩形范围内元素的总和,该子矩阵的左上角为 (row1, col1) ,右下角为 (row2, col2) 。

实现 NumMatrix 类:

NumMatrix(int[][] matrix) 给定整数矩阵 matrix 进行初始化

int sumRegion(int row1, int col1, int row2, int col2) 返回左上角 (row1, col1) 、右下角 (row2, col2) 的子矩阵的元素总和。


示例 1:

输入: 

["NumMatrix","sumRegion","sumRegion","sumRegion"]

[[[[3,0,1,4,2],[5,6,3,2,1],[1,2,0,1,5],[4,1,0,1,7],[1,0,3,0,5]]],[2,1,4,3],[1,1,2,2],[1,2,2,4]]

输出: 

[null, 8, 11, 12]

解释:

NumMatrix numMatrix = new NumMatrix([[3,0,1,4,2],[5,6,3,2,1],[1,2,0,1,5],[4,1,0,1,7],[1,0,3,0,5]]]);

numMatrix.sumRegion(2, 1, 4, 3); // return 8 (红色矩形框的元素总和)

numMatrix.sumRegion(1, 1, 2, 2); // return 11 (绿色矩形框的元素总和)

numMatrix.sumRegion(1, 2, 2, 4); // return 12 (蓝色矩形框的元素总和)


提示:

m == matrix.length

n == matrix[i].length

1 <= m, n <= 200

-105 <= matrix[i][j] <= 105

0 <= row1 <= row2 < m

0 <= col1 <= col2 < n

最多调用 104 次 sumRegion 方法

class NumMatrix:
def __init__(self, matrix: List[List[int]]):
sums = matrix
for i in range(0,len(sums)):
for j in range(0,len(sums[0])):
if i==0 and j==0:
continue
if i==0:
sums[i][j] += sums[i][j-1]
elif j==0:
sums[i][j] += sums[i-1][j]
else:
sums[i][j] += sums[i][j-1] + sums[i-1][j] - sums[i-1][j-1]
self.sums = sums

def sumRegion2(self, row: int, col) -> int:
if row < 0 or col < 0:
return 0
return self.sums[row][col]

def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int:
row1 -= 1
col1 -= 1
return NumMatrix.sumRegion2(self,row2,col2) + NumMatrix.sumRegion2(self,row1,col1) \
- NumMatrix.sumRegion2(self,row1,col2) - NumMatrix.sumRegion2(self,row2,col1)

剑指 Offer II 014. 字符串中的变位词

给定两个字符串 s1 和 s2,写一个函数来判断 s2 是否包含 s1 的某个变位词。

换句话说,第一个字符串的排列之一是第二个字符串的 子串 。

示例 1:

输入: s1 = "ab" s2 = "eidbaooo"

输出: True

解释: s2 包含 s1 的排列之一 ("ba").

示例 2:

输入: s1= "ab" s2 = "eidboaoo"

输出: False


提示:

1 <= s1.length, s2.length <= 104

s1 和 s2 仅包含小写字母

import string

class Solution:
def checkInclusion(self, s1: str, s2: str) -> bool:
dict = {'a':'0'}
for c in string.ascii_lowercase:
dict[c] = 0
for c in s1:
dict[c] += 1
if len(s1) > len(s2):
return False
for i in range(0,len(s1)):
dict[s2[i]] -= 1
flag = True
for c in string.ascii_lowercase:
if dict[c] != 0:
flag = False
if flag:
return True
for i in range(len(s1),len(s2)):
dict[s2[i]] -= 1
dict[s2[i-len(s1)]] += 1
flag = True
for c in string.ascii_lowercase:
if dict[c] != 0:
flag = False
if flag:
return True
return False

剑指 Offer II 015. 字符串中的所有变位词

给定两个字符串 s 和 p,找到 s 中所有 p 的 变位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

变位词 指字母相同,但排列不同的字符串。

示例 1:

输入: s = "cbaebabacd", p = "abc"

输出: [0,6]

解释:

起始索引等于 0 的子串是 "cba", 它是 "abc" 的变位词。

起始索引等于 6 的子串是 "bac", 它是 "abc" 的变位词。

 示例 2:

输入: s = "abab", p = "ab"

输出: [0,1,2]

解释:

起始索引等于 0 的子串是 "ab", 它是 "ab" 的变位词。

起始索引等于 1 的子串是 "ba", 它是 "ab" 的变位词。

起始索引等于 2 的子串是 "ab", 它是 "ab" 的变位词。


提示:

1 <= s.length, p.length <= 3 * 104

s 和 p 仅包含小写字母

import string

class Solution:
def findAnagrams(self, s: str, p: str) -> List[int]:
dict = {'a':'0'}
ans = []
for c in string.ascii_lowercase:
dict[c] = 0
for c in p:
dict[c] += 1
if len(p) > len(s):
return ans
for i in range(0,len(p)):
dict[s[i]] -= 1
flag = True
for c in string.ascii_lowercase:
if dict[c] != 0:
flag = False
if flag:
ans.append(0)
for i in range(len(p),len(s)):
dict[s[i]] -= 1
dict[s[i-len(p)]] += 1
flag = True
for c in string.ascii_lowercase:
if dict[c] != 0:
flag = False
if flag:
ans.append(i-len(p)+1)
return ans

剑指 Offer II 016. 不含重复字符的最长子字符串

剑指 Offer 48. 最长不含重复字符的子字符串 ​​​

剑指 Offer II 017. 含有所有字符的最短字符串

76. 最小覆盖子串 ​

剑指 Offer II 018. 有效的回文

125. 验证回文串 ​

剑指 Offer II 019. 最多删除一个字符得到回文

给定一个非空字符串 s,请判断如果 最多 从字符串中删除一个字符能否得到一个回文字符串。

示例 1:

输入: s = "aba"

输出: true

示例 2:

输入: s = "abca"

输出: true

解释: 可以删除 "c" 字符 或者 "b" 字符

示例 3:

输入: s = "abc"

输出: false


提示:

1 <= s.length <= 105

s 由小写英文字母组成

class Solution {
public:
bool isPalindrome(string s)
{
for(int i=0,j=s.length()-1;i<j;i++,j--)if(s[i]!=s[j])return false;
return true;
}
bool validPalindrome(string s) {
for(int i=0,j=s.length()-1;i<j;i++,j--)if(s[i]!=s[j]){
if(isPalindrome(s.substr(i,j-i)) || isPalindrome(s.substr(i+1,j-i)))return true;
return false;
}
return true;
}
};

剑指 Offer II 021. 删除链表的倒数第 n 个结点

19. 删除链表的倒数第N个节点 ​​​

剑指 Offer II 022. 链表中环的入口节点

142. 环形链表 II ​

剑指 Offer II 023. 两个链表的第一个重合节点

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

剑指 Offer II 024. 反转链表

剑指 Offer 24. 反转链表 ​​​

剑指 Offer II 026. 重排链表

143. 重排链表 ​

剑指 Offer II 027. 回文链表

234. 回文链表 ​​

剑指 Offer II 031. 最近最少使用缓存

146. LRU 缓存机制​

剑指 Offer II 032. 有效的变位词

给定两个字符串 s 和 t ,编写一个函数来判断它们是不是一组变位词(字母异位词)。

注意:若 s 和 t 中每个字符出现的次数都相同且字符顺序不完全相同,则称 s 和 t 互为变位词(字母异位词)。

示例 1:

输入: s = "anagram", t = "nagaram"

输出: true

示例 2:

输入: s = "rat", t = "car"

输出: false

示例 3:

输入: s = "a", t = "a"

输出: false


提示:

1 <= s.length, t.length <= 5 * 104

s and t 仅包含小写字母


int getHash(string s)
{
int su=0;
for(int i=0;i<s.length();i++)su+=pow(s[i]-'a'+1,5),su%=12345678;
return su;
}

class Solution {
public:
bool isAnagram(string s, string t) {
if(s==t)return false;
return getHash(s)==getHash(t);
}
};

剑指 Offer II 033. 变位词组

49. 字母异位词分组 ​

剑指 Offer II 044. 二叉树每层的最大值

给定一棵二叉树的根节点 root ,请找出该二叉树中每一层的最大值。

示例1:

输入: root = [1,3,2,5,3,null,9]

输出: [1,3,9]

解释:

          1

         / \

        3   2

       / \   \  

      5   3   9 

示例2:

输入: root = [1,2,3]

输出: [1,3]

解释:

          1

         / \

        2   3

示例3:

输入: root = [1]

输出: [1]

示例4:

输入: root = [1,null,2]

输出: [1,2]

解释:      

           1 

            \

             2     

示例5:

输入: root = []

输出: []


提示:

二叉树的节点个数的范围是 [0,104]

-231 <= Node.val <= 231 - 1

bool isGreater(int a, int b)
{
return a > b;
}
template<typename T>
vector<T> mergeVector(vector<T> a, vector<T> b)
{
vector<T> ans;
int i;
for (i = 0; i < a.size() && i < b.size(); i++) {
if (isGreater(a[i], b[i]))ans.push_back(a[i]);
else ans.push_back(b[i]);
}
for (; i < a.size(); i++)ans.push_back(a[i]);
for (; i < b.size(); i++)ans.push_back(b[i]);
return ans;
}

class Solution {
public:
vector<int> largestValues(TreeNode* root) {
vector<int> ans;
if (!root)return ans;
ans = mergeVector(largestValues(root->left), largestValues(root->right));
ans.insert(ans.begin(), root->val);
return ans;
}
};

剑指 Offer II 046. 二叉树的右侧视图

199. 二叉树的右视图 ​

剑指 Offer II 049. 从根节点到叶节点的路径数字之和

129. 求根到叶子节点数字之和 ​​​

剑指 Offer II 053. 二叉搜索树中的中序后继

285. 二叉搜索树中的中序后继 ​​​

剑指 Offer II 060. 出现频率最高的 k 个数字

347. 前 K 个高频元素​

剑指 Offer II 061. 和最小的 k 个数对

373. 查找和最小的K对数字 ​​​

剑指 Offer II 067. 最大的异或

421. 数组中两个数的最大异或值​

剑指 Offer II 070. 排序数组中只出现一次的数字

540. 有序数组中的单一元素 ​

剑指 Offer II 071. 按权重生成随机数

给定一个正整数数组 w ,其中 w[i] 代表下标 i 的权重(下标从 0 开始),请写一个函数 pickIndex ,它可以随机地获取下标 i,选取下标 i 的概率与 w[i] 成正比。

例如,对于 w = [1, 3],挑选下标 0 的概率为 1 / (1 + 3) = 0.25 (即,25%),而选取下标 1 的概率为 3 / (1 + 3) = 0.75(即,75%)。

也就是说,选取下标 i 的概率为 w[i] / sum(w) 。

示例 1:

输入:

inputs = ["Solution","pickIndex"]

inputs = [[[1]],[]]

输出:

[null,0]

解释:

Solution solution = new Solution([1]);

solution.pickIndex(); // 返回 0,因为数组中只有一个元素,所以唯一的选择是返回下标 0。

示例 2:

输入:

inputs = ["Solution","pickIndex","pickIndex","pickIndex","pickIndex","pickIndex"]

inputs = [[[1,3]],[],[],[],[],[]]

输出:

[null,1,1,1,1,0]

解释:

Solution solution = new Solution([1, 3]);

solution.pickIndex(); // 返回 1,返回下标 1,返回该下标概率为 3/4 。

solution.pickIndex(); // 返回 1

solution.pickIndex(); // 返回 1

solution.pickIndex(); // 返回 1

solution.pickIndex(); // 返回 0,返回下标 0,返回该下标概率为 1/4 。

由于这是一个随机问题,允许多个答案,因此下列输出都可以被认为是正确的:

[null,1,1,1,1,0]

[null,1,1,1,1,1]

[null,1,1,1,0,0]

[null,1,1,1,0,1]

[null,1,0,1,0,0]

......

诸若此类。


提示:

1 <= w.length <= 10000

1 <= w[i] <= 10^5

pickIndex 将被调用不超过 10000 次

class Solution {
public:
vector<double> v;
int s;
Solution(vector<int>& w) {
v.resize(w.size());
s = 0;
for(int i=0;i<w.size();i++){
s+=w[i],v[i]=w[i];
if(i)v[i]+=v[i-1];
}
for(int i=0;i<w.size();i++)v[i]/=s;
}
double getRand()
{
return rand()*1.0/RAND_MAX;
}

int pickIndex() {
double r = getRand();
int low=0,high=v.size();
if(r <= v[0])return 0;
while(low < high-1){
int mid = (high + low)/2;
if(r < v[mid])high = mid;
else low = mid;
}
if(r < v[low+1])return low+1;
else return high;
}
};

剑指 Offer II 072. 求平方根

69. x 的平方根​

剑指 Offer II 073. 狒狒吃香蕉

875. 爱吃香蕉的珂珂 ​​​

剑指 Offer II 074. 合并区间

56. 合并区间​

剑指 Offer II 076. 数组中的第 k 大的数字

215. 数组中的第K个最大元素 ​​​

剑指 Offer II 077. 链表排序

148. 排序链表​

剑指 Offer II 085. 生成匹配的括号

22. 括号生成​

剑指 Offer II 087. 复原 IP

93. 复原IP地址​

剑指 Offer II 093. 最长斐波那契数列

873. 最长的斐波那契子序列的长度​

剑指 Offer II 095. 最长公共子序列

1143. 最长公共子序列​

剑指 Offer II 099. 最小路径之和

64. 最小路径和 ​

剑指 Offer II 101. 分割等和子集

416. 分割等和子集​

剑指 Offer II 103. 最少的硬币数目

322. 零钱兑换​

剑指 Offer II 107. 矩阵中的距离

542. 01 矩阵​

剑指 Offer II 113. 课程顺序

210. 课程表 II​