给定一个有相同值的二叉搜索树(BST),找出 BST 中的所有众数(出现频率最高的元素)。
总结
二叉搜索树的中序遍历是递增顺序,把问题转换为求递增数组众数即可。
class Solution {
int preVal = 0, curTimes = 0, maxTimes = 0;
ArrayList<Integer> list = new ArrayList<Integer>();
public int[] findMode(TreeNode root) {
traversal(root);
//list转换为int[]
int size = list.size();
int[] ans = new int[size];
for(int i = 0; i < size; i++)
ans[i] = list.get(i);
return ans;
}
public void traversal(TreeNode root){
if(root == null) return;
traversal(root.left);
//判断当前值与上一个值的关系, 更新 curTimes 和 preVal
if(preVal == root.val){
curTimes++;
}else{
preVal = root.val;
curTimes = 1;
}
//判断当前数量与最大数量的关系, 更新 list 和 maxTimes
if(curTimes == maxTimes){
list.add(root.val);
}else if(curTimes > maxTimes){
list.clear();
list.add(root.val);
maxTimes = curTimes;
}
traversal(root.right);
}
}
给定一个字符串和一个整数 k,你需要对从字符串开头算起的每个 2k 个字符的前k个字符进行反转。如果剩余少于 k 个字符,则将剩余的所有全部反转。如果有小于 2k 但大于或等于 k 个字符,则反转前 k 个字符,并将剩余的字符保持原样。
示例:
输入: s = “abcdefg”, k = 2
输出: “bacdfeg”
总结
像写诗一样写代码就是这样吧
class Solution {
public String reverseStr(String s, int k) {
char[] a = s.toCharArray();
for (int start = 0; start < a.length; start += 2 * k) {
int i = start, j = Math.min(start + k - 1, a.length - 1);
while (i < j) {
char tmp = a[i];
a[i++] = a[j];
a[j--] = tmp;
}
}
return new String(a);
}
}
和谐数组是指一个数组里元素的最大值和最小值之间的差别正好是1。
现在,给定一个整数数组,你需要在所有可能的子序列中找到最长的和谐子序列的长度。
示例:
输入: [1,3,2,2,5,2,3,7]
输出: 5
原因: 最长的和谐数组是:[3,2,2,2,3]
public class Solution {
public int findLHS(int[] nums) {
HashMap<Integer, Integer> map = new HashMap<>();
int res = 0;
for (int num: nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
if (map.containsKey(num + 1))
res = Math.max(res, map.get(num) + map.get(num + 1));
if (map.containsKey(num - 1))
res = Math.max(res, map.get(num) + map.get(num - 1));
}
return res;
}
}
class Solution {
public int findLHS(int[] nums) {
Arrays.sort(nums);
int start = 0, end = 0;
int res = 0;
for(int i = 0; i < nums.length-1; i++) {
if(nums[i] == nums[i+1]) {
end++;
}else if(nums[i+1] - nums[i] == 1) {
if(i+1 == nums.length-1) { // 到尾部了
end++;
res = Math.res(res, end-start+1);
}else { // 直接找到于当前数相等的最后一位
int tmp = i+1;
end++;
i++;
while(i < nums.length-1 && nums[i] == nums[i+1]) {
end++;
i++;
}
res = Math.res(res, end-start+1);
start = tmp;
i--;
}
}else { // [..., 2, 2, 4, ...]
start = i+1;
end = i+1;
}
}
return res;
}
}
集合 S 包含从1到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个元素复制了成了集合里面的另外一个元素的值,导致集合丢失了一个整数并且有一个元素重复。
给定一个数组 nums 代表了集合 S 发生错误后的结果。你的任务是首先寻找到重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。
示例:
输入: nums = [1,2,2,4]
输出: [2,3]
总结
一种针对特殊情况的排序算法
class Solution {
public int[] findErrorNums(int[] nums) {
for(int i = 0; i < nums.length; i++){
while(nums[i] != (i + 1) && nums[i] != nums[nums[i] - 1])
swap(nums, nums[i] - 1, i);
}
for(int i = 0; i < nums.length; i++){
if(nums[i] != i + 1)
return new int[]{nums[i], i + 1};
}
return null;
}
private void swap(int[] nums, int i, int j){
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
给定一个长度为 n 的整数数组,你的任务是判断在最多改变 1 个元素的情况下,该数组能否变成一个非递减数列。
我们是这样定义一个非递减数列的: 对于数组中所有的 i (1 <= i < n),满足 array[i] <= array[i + 1]。
示例:
输入: [4,2,3]
输出: True
解释: 你可以通过把第一个4变成1来使得它成为一个非递减数列。
总结
这题其实并不简单,如何处理[3,4,2,3]是个难点
class Solution {
public boolean checkPossibility(int[] nums) {
int cnt = 0;
for (int i = 1; i < nums.length && cnt < 2; i++) {
if (nums[i-1] <= nums[i])
continue;
cnt++;
if (i-2>=0 && nums[i-2] > nums[i])
nums[i] = nums[i-1];
}
return cnt <= 1;
}
}
给定一个非空特殊的二叉树,每个节点都是正数,并且每个节点的子节点数量只能为 2 或 0。如果一个节点有两个子节点的话,那么这个节点的值不大于它的子节点的值。
给出这样的一个二叉树,你需要输出所有节点中的第二小的值。如果第二小的值不存在的话,输出 -1
class Solution {
public int findSecondMinimumValue(TreeNode root) {
return myfun(root, root.val);
}
public int myfun(TreeNode root, int val) {
if (root == null)
return -1;
if (root.val > val)
return root.val;
int l = myfun(root.left, val);
int r = myfun(root.right, val);
if (l > val && r > val)
return Math.min(l,r);
return Math.max(l,r);
}
}
给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。
示例:
输入: “abca”
输出: True
解释: 你可以删除c字符。
总结
代码虽然重复了,但是是一种很有一种启发性的写法
class Solution {
public boolean validPalindrome(String s) {
int i = 0, j = s.length() - 1;
while(i < j){
if(s.charAt(i) != s.charAt(j))
return isValid(s, i + 1, j) || isValid(s, i, j - 1);
i++;
j--;
}
return true;
}
public boolean isValid(String s, int i, int j){
while(i < j){
if(s.charAt(i) != s.charAt(j))
return false;
i++;
j--;
}
return true;
}
}
给定一个正整数,检查他是否为交替位二进制数:换句话说,就是他的二进制数相邻的两个位数永不相等。
示例:
输入: 5
输出: True
解释:
5的二进制数是: 101
class Solution {
public boolean hasAlternatingBits(int n) {
int temp = n^(n>>1);
return (temp&(temp+1)) == 0;
// return (n & (n>>1)) == 0; // 不能这样写, 因为有 1000 这种情况
}
}
给定一个字符串 s,计算具有相同数量0和1的非空(连续)子字符串的数量,并且这些子字符串中的所有0和所有1都是组合在一起的。
重复出现的子串要计算它们出现的次数。
示例:
输入: “00110011”
输出: 6
解释: 有6个子串具有相同数量的连续1和0:“0011”,“01”,“1100”,“10”,“0011” 和 “01”。
请注意,一些重复出现的子串要计算它们出现的次数。
另外,“00110011”不是有效的子串,因为所有的0(和1)没有组合在一起。
class Solution {
public int countBinarySubstrings(String s) {
int last = 0, cur = 1, res = 0;
for(int i = 1; i < s.length(); i++) {
if(s.charAt(i) == s.charAt(i-1))
cur++;
else {
last = cur;
cur = 1;
}
if(last >= cur) res++; // 0011 包含 01
}
return res;
}
}
有两种特殊字符。第一种字符可以用一比特0来表示。第二种字符可以用两比特(10 或 11)来表示。
现给一个由若干比特组成的字符串。问最后一个字符是否必定为一个一比特字符。给定的字符串总是由0结束。
示例 1:
输入:
bits = [1, 0, 0]
输出: True
解释:
唯一的编码方式是一个两比特字符和一个一比特字符。所以最后一个字符是一比特字符。
示例 2:
输入:
bits = [1, 1, 1, 0]
输出: False
解释:
唯一的编码方式是两比特字符和两比特字符。所以最后一个字符不是一比特字符。
class Solution {
public boolean isOneBitCharacter(int[] bits) {
int i = 0;
while (i < bits.length - 1)
i += bits[i] + 1;
return i == bits.length - 1;
}
}
class Solution {
public boolean isOneBitCharacter(int[] bits) {
int i = bits.length - 2;
while (i >= 0 && bits[i] > 0) i--;
return (bits.length - i) % 2 == 0;
}
}
给定一个整数类型的数组 nums,请编写一个能够返回数组“中心索引”的方法。
我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。
如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个。
示例:
输入:
nums = [1, 7, 3, 6, 5, 6]
输出: 3
解释:
索引3 (nums[3] = 6) 的左侧数之和(1 + 7 + 3 = 11),与右侧数之和(5 + 6 = 11)相等。
同时, 3 也是第一个符合要求的中心索引。
class Solution {
public int pivotIndex(int[] nums) {
int sum = 0;
int leSum = 0;
for(int i : nums)
sum += i;
for(int i = 0; i < nums.length; i++) {
if(leSum * 2 + nums[i] == sum)
return i;
leSum += nums[i];
}
return -1;
}
}
ERROR CODE
遇到有负数(或者全非正数)的不能处理
class Solution {
public int pivotIndex(int[] nums) {
int le = 0, ri = nums.length-1;
int lum = 0, rum = 0;
boolean isL = false;
while(le < ri) {
if(lum < rum) {
isL = false;
lum += nums[le++];
}else {
isL = true;
rum += nums[ri--];
}
}
if(lum == rum) return isL ? le : ri;
return -1;
}
}
在一个给定的数组nums中,总是存在一个最大元素 。
查找数组中的最大元素是否至少是数组中每个其他数字的两倍。
如果是,则返回最大元素的索引,否则返回-1。
示例:
输入: nums = [3, 6, 1, 0]
输出: 1
解释: 6是最大的整数, 对于数组中的其他整数,
6大于数组中其他元素的两倍。6的索引是1, 所以我们返回1.
总结
仔细想想,为什么我们要将最大值与所有元素进行比较呢?如果我们找到第二大的元素,将它的两倍的值与最大值进行比较,不就能证明最大值是否大于所有元素两倍的值吗?
by: Pushy
class Solution {
public int dominantIndex(int[] nums) {
int max = 0, idx = 0, less = 1;
for (int i = 0; i < nums.length; i++) {
if (nums[i] > max) {
less = max;
max = nums[i];
idx = i;
} else if (nums[i] > less) {
less = nums[i];
}
}
return max >= (less * 2) ? idx : -1;
}
}
在一根无限长的数轴上,你站在0的位置。终点在target的位置。
每次你可以选择向左或向右移动。第 n 次移动(从 1 开始),可以走 n 步。
返回到达终点需要的最小移动次数。
示例:
输入: target = 2
输出: 3
解释:
第一次移动,从 0 到 1 。
第二次移动,从 1 到 -1 。
第三次移动,从 -1 到 2
总结
假设我们移动了 k 次,每次任意地向左或向右移动,那么最终到达的位置实际上就是将 1, 2, 3, …, k 这 k 个数添加正号(向右移动)或负号(向左移动)后求和的值。并且如果最终到达的位置为 t 且 t < 0,那么我们可以将这 k 个数的符号全部取反,这样求和的值为 -t > 0。因此我们只考虑题目中 target > 0 的情况。
我们沿用上面的符号,设 k 为最小的满足 S = 1 + 2 + … + k >= target 的正整数,如果 S == target 那么答案显然是 k。如果 S > target,那么我们需要将一些正号变为负号,使得最后求和的值等于 target。当前比 target 多出了 delta = S - target,那么我们需要在 1, 2, …, k 中找到若干个数变成负号,并且它们的和为 delta / 2。可以证明一定能找到和为 delta / 2 的若干个数:如果 delta / 2 <= k,那么只需要选出 delta / 2 即可;如果 delta / 2 > k,那么先选出 k,再从 1, 2, 3, …, k - 1 中选出若干个数使得它们的和为 delta / 2 - k,这样就把原问题变成了一个规模更小的子问题。显然 delta / 2 <= 1 + 2 + … + k,因此一定能选出若干个数。
上面只适用于 delta 为偶数的情况。若 delta 为奇数,则 delta / 2 不为整数,因此无法选出。此时我们只能考虑 k + 1 和 k + 2,求出 1 到 k + 1 的和以及 1 到 k + 2 的和,它们中必有一个和 1 到 k 的和的奇偶性不同,此时 delta 变为偶数,可以选出若干个数。
class Solution {
public int reachNumber(int target) {
int tar = Math.abs(target);
int idx = 0;
int sum = 0;
while(sum < tar){
idx++;
sum += idx;
}
int dt = sum - tar;
if(dt % 2 == 0)
return idx;
else{
if(idx % 2 == 0)
return idx+1;
else
return idx+2;
}
}
}
class Solution {
public int reachNumber(int target) {
target = Math.abs(target);
int k = 0;
while (target > 0)
target -= ++k;
return target % 2 == 0 ? k : k + 1 + k%2;
}
}
作者:LeetCode
链接:https://leetcode-cn.com/problems/reach-a-number/solution/dao-da-zhong-dian-shu-zi-by-leetcode/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。