*424. Longest Repeating Character Replacement
int characterReplacement(string s, int k) {
if (s.size()==0){
return 0;
}
int alphabet[26];
fill(alphabet,alphabet+26,0);
int left=0;
int right=0;
int res=0;
while (right<s.size()){
alphabet[s[right]-'A']++;
while (right-left+1-*max_element(alphabet,alphabet+26)>k){
alphabet[s[left]-'A']--;
left++;
}
res=max(res,right-left+1);
right++;
}
return res;
}
429. N-ary Tree Level Order Traversal
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> ans=new ArrayList<>();
if (root==null){
return ans;
}
Queue<Node> queue=new LinkedList<>();
Queue<Node> curr=new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()){
List<Integer> currLayerNodes=new ArrayList<>();
while (!queue.isEmpty()){
Node node=queue.poll();
if (node.children!=null){
for (Node child:node.children){
curr.offer(child);
}
}
currLayerNodes.add(node.val);
}
queue.addAll(curr);
curr.clear();
ans.add(currLayerNodes);
}
return ans;
}
*433. Minimum Genetic Mutation
class Solution {
public static final char[] charSet = {'A', 'G', 'C', 'T'};
public HashMap<String, Integer> map = new HashMap<>();
public int minMutation(String startGene, String endGene, String[] bank) {
HashSet<String> alphabet = new HashSet<>(bank.length);
Collections.addAll(alphabet, bank);
map.put(startGene, 0);
Deque<String> deque = new ArrayDeque<>();
deque.addLast(startGene);
while (!deque.isEmpty()) {
int size = deque.size();
while (size > 0) {
String s = deque.pollFirst();
int currStep = map.get(s);
char[] charArr = s.toCharArray();
for (int i = 0; i < 8; i++) {
char[] sourceCopy = charArr.clone();
for (char ch : charSet) {
if (sourceCopy[i] == ch) {
continue;
}
sourceCopy[i] = ch;
String variant = new String(sourceCopy);
if (!alphabet.contains(variant)) continue;
if (endGene.equals(variant)) {
return currStep + 1;
}
if (map.containsKey(variant)) continue;
map.put(variant, currStep + 1);
deque.addLast(variant);
}
}
size--;
}
}
return -1;
}
}
434. Number of Segments in a String
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Solution {
String regex="\\S+";
Pattern pattern=Pattern.compile(regex);
public int countSegments(String s) {
if (s.isEmpty()){
return 0;
}
Matcher matcher=pattern.matcher(s);
String[] res=s.split(" ");
int cnt=0;
while (matcher.find()){
cnt++;
}
return cnt;
}
}
*436. Find Right Interval
排序+二分 注意 mid的对left以及right取值影响
class Solution {
public int[] findRightInterval(int[][] its) {
int n = its.length;
int[][] clone = new int[n][2];
for (int i = 0; i < n; i++) clone[i] = new int[]{its[i][0], i};
Arrays.sort(clone, (a,b)->a[0]-b[0]);
int[] ans = new int[n];
for (int i = 0; i < n; i++) {
int l = 0, r = n - 1;
while (l < r) {
int mid = l + r >> 1;
if (clone[mid][0] >= its[i][1]) r = mid;
else l = mid + 1;
}
ans[i] = clone[r][0] >= its[i][1] ? clone[r][1] : -1;
}
return ans;
}
}
双指针(莫队思想)
更进一步,在解法一中我们并没有对求解询问的顺序进行调整,这导致了我们不得不每次都在整个左端点序列中进行二分。
朴素处理询问的方式,需要每次对整个序列进行扫描,复杂度为 O ( n 2 ) O(n^2) O(n2)实际上,如果我们按照「右端点从小到大」的顺序处理询问,其每个询问对应的「最右区间的左端点」也具有单调特性。
因此,我们可以运用莫队思想:通过调整询问的处理顺序,来减少扫描目标位置的指针移动次数。将其从「必然进行 O ( n 2 ) O(n^2) O(n2)次移动」优化为「最多不超过n次移动」,从而将 构造答案 的复杂度从 O ( n 2 ) O(n^2) O(n2)优化为 O ( n ) O(n) O(n)。
*437. Path Sum III
树的遍历 + DFS
class Solution {
public int res=0;
public static long target;
public int pathSum(TreeNode root, int targetSum) {
target=targetSum;
dfsStartRoute(root);
return res;
}
public void dfsStartRoute(TreeNode root){
if (root==null){
return;
}
dfsSubRoute(root, 0);
dfsStartRoute(root.left);
dfsStartRoute(root.right);
}
public void dfsSubRoute(TreeNode root,long currSum){
if (currSum+root.val==target){
res++;
}
if (root.left!=null){
dfsSubRoute(root.left,currSum+root.val);
}
if (root.right!=null){
dfsSubRoute(root.right,currSum+root.val);
}
}
}
*树的遍历 + 前缀和
在「解法一」中,我们统计的是以每个节点为根的(往下的)所有路径,也就是说统计的是以每个节点为「路径开头」的所有合法路径。
本题的一个优化切入点为「路径只能往下」,因此如果我们转换一下,统计以每个节点为「路径结尾」的合法数量的话,配合原本就是「从上往下」进行的数的遍历(最完整的路径必然是从原始根节点到当前节点的唯一路径),相当于只需要在完整路径中找到有多少个节点到当前节点的路径总和为
targetSum。于是这个树上问题彻底转换一维问题:求解从原始起点(根节点)到当前节点 b 的路径中,有多少节点 a 满足:
s
u
m
[
a
.
.
.
b
]
=
t
a
r
g
e
t
S
u
m
sum[a...b]=targetSum
sum[a...b]=targetSum,由于从原始起点(根节点)到当前节点的路径唯一,因此这其实是一个「一维前缀和」问题。
具体的,我们可以在进行树的遍历时,记录下从原始根节点 root 到当前节点 cur 路径中,从 root 到任意中间节点 x 的路径总和,配合哈希表,快速找到满足以 cur
为「路径结尾」的、使得路径总和为 targetSum
的目标「路径起点」有多少个。
一些细节:由于我们只能统计往下的路径,但是树的遍历会同时搜索两个方向的子树。因此我们应当在搜索完以某个节点为根的左右子树之后,应当回溯地将路径总和从哈希表中删除,防止统计到跨越两个方向的路径。
438. Find All Anagrams in a String
public List<Integer> findAnagrams(String s, String p) {
List<Integer> res=new ArrayList<>();
int windowLength=p.length();
if (s.length()<windowLength){
return res;
}
int[] alphabet=new int[256];
for (char ch:p.toCharArray()){
alphabet[ch]++;
}
int waitToMinus=p.length();
char[] sArr=s.toCharArray();
int right=windowLength-1;
for (int i=0;i<=right;i++){
if (alphabet[sArr[i]]>0){
waitToMinus--;
}
alphabet[sArr[i]]--;
}
if (waitToMinus==0){
res.add(0);
}
int left=0;
right++;
while (right<s.length()){
alphabet[sArr[left]]++;
if (alphabet[sArr[left]]>0){
waitToMinus++;
}
if (alphabet[sArr[right]]>0){
waitToMinus--;
}
alphabet[sArr[right]]--;
if (waitToMinus==0){
res.add(left+1);
}
right++;
left++;
}
return res;
}
440. K-th Smallest in Lexicographical Order Source
public int findKthNumber(int n, int k) {
if(n<k||k<1){
return 0;
}
if(n<10){
return k;
}
long curr=1;
k--;
while(k>0){
long steps=0,first=curr, last=curr+1;
while (first<=n){
//限制该位得数字为0-9
steps+=Math.min(n+1,last)-first;
first*=10;
last*=10;
}
// 当前steps超位,需要进位
if(steps<=k){
curr++;
k-=steps;
}
else {
curr*=10;
k--;
}
}
return (int)curr;
}
441. Arranging Coins
class Solution {
public:
int arrangeCoins(int _n) {
long layers = 0;
long n = _n;
while ((long)((layers + 1) * layers) / 2 < n) {
layers += 3;
}
while ((long)((layers + 1) * layers)/2 > n){
layers--;
}
if ((long)((layers + 1) * layers)/2 == n){
return layers;
}
return layers;
}
};
448. Find All Numbers Disappeared in an Array
vector<int> findDisappearedNumbers(vector<int>& nums) {
vector<int> res;
for (int i = 0; i < nums.size(); ++i) {
int curr_val= abs(nums[i])%nums.size();
int target_val=abs(nums[curr_val]);
nums[curr_val]=-target_val;
}
if (nums[0]>0){
res.push_back(nums.size());
}
for (int i = 1; i < nums.size(); ++i) {
if (nums[i]>0){
res.push_back(i);
}
}
return res;
}
*450. Delete Node in a BST