代码有借鉴大神的写法,由于不清楚是哪位大神,所以在这里表示感谢~~~~
- 摆动排序II
- 坏了的计算器
- 删除造列II
- 移除掉k位数字
- 整数替换
- 重构字符串
1. 给定一个无序的数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]… 的顺序。
示例 1:
输入: nums = [1, 5, 1, 1, 6, 4]
输出: 一个可能的答案是 [1, 4, 1, 5, 1, 6]
示例 2:
输入: nums = [1, 3, 2, 2, 3, 1]
输出: 一个可能的答案是 [2, 3, 1, 3, 1, 2]
[1,5,1,1,6,4]
[1,1,2,1,2,2,1]
public static void wiggleSort(int[] nums) {
Arrays.sort(nums);
int start=(nums.length+1)/2-1;
int end=nums.length-1;
int [] temp=new int[nums.length];
int index=0;
while(start>=0 && end>=(nums.length+1)/2) {
temp[index++]=nums[start--];
temp[index++]=nums[end--];
}
if(nums.length%2==1) {
temp[index]=nums[start];
}
//
// System.out.println(Arrays.toString(temp));
for(int i=0;i<nums.length;i++) {
nums[i]=temp[i];
}
}
2. 在显示着数字的坏计算器上,我们可以执行以下两种操作:
双倍(Double):将显示屏上的数字乘 2;
递减(Decrement):将显示屏上的数字减 1 。
最初,计算器显示数字 X。
返回显示数字 Y 所需的最小操作数。
示例 1:
输入:X = 2, Y = 3
输出:2
解释:先进行双倍运算,然后再进行递减运算 {2 -> 4 -> 3}.
示例 2:
输入:X = 5, Y = 8
输出:2
解释:先递减,再双倍 {5 -> 4 -> 8}.
示例 3:
输入:X = 3, Y = 10
输出:3
解释:先双倍,然后递减,再双倍 {3 -> 6 -> 5 -> 10}.
示例 4:
输入:X = 1024, Y = 1
输出:1023
解释:执行递减运算 1023 次
public static int brokenCalc(int X, int Y) {
int n=0;
while(X<Y) {
if(Y%2==0) {
Y=Y/2;
n++;
}else {
Y=(Y+1)/2;
n+=2;
}
}
return n+X-Y;
}
3. 给定由 N 个小写字母字符串组成的数组 A,其中每个字符串长度相等。
选取一个删除索引序列,对于 A 中的每个字符串,删除对应每个索引处的字符。
比如,有 A = [“abcdef”, “uvwxyz”],删除索引序列 {0, 2, 3},删除后 A 为[“bef”, “vyz”]。
假设,我们选择了一组删除索引 D,那么在执行删除操作之后,最终得到的数组的元素是按 字典序(A[0] <= A[1] <= A[2] … <= A[A.length - 1])排列的,然后请你返回 D.length 的最小可能值。
示例 1:
输入:[“ca”,“bb”,“ac”]
输出:1
解释:
删除第一列后,A = [“a”, “b”, “c”]。
现在 A 中元素是按字典排列的 (即,A[0] <= A[1] <= A[2])。
我们至少需要进行 1 次删除,因为最初 A 不是按字典序排列的,所以答案是 1。
示例 2:
输入:[“xc”,“yb”,“za”]
输出:0
解释:
A 的列已经是按字典序排列了,所以我们不需要删除任何东西。
注意 A 的行不需要按字典序排列。
也就是说,A[0][0] <= A[0][1] <= … 不一定成立。
示例 3:
输入:[“zyx”,“wvu”,“tsr”]
输出:3
解释:
我们必须删掉每一列。
public static int minDeletionSize(String[] strs) {
if (strs == null || strs.length < 2) {
return 0;
}
int arrLen = strs.length;
int strLen = strs[0].length();
// 如果cuts[i] = true, 那么我们不需要再检查 strs[i][j] > strs[i+1][j]
boolean[] cuts = new boolean[arrLen];
int ans = 0;
boolean delete;
for (int j = 0; j < strLen; j++) {
delete = false;
for (int i = 0; i < arrLen - 1; i++) {
if (!cuts[i] && strs[i].charAt(j) > strs[i + 1].charAt(j)) {
ans++;
delete = true;
break;
}
}
if (!delete) {
// 更新cuts
for (int i = 0; i < arrLen - 1; i++) {
if (strs[i].charAt(j) < strs[i + 1].charAt(j)) {
cuts[i] = true;
}
}
}
}
return ans;
}
4. 给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。
注意:
num 的长度小于 10002 且 ≥ k。
num 不会包含任何前导零。
示例 1 :
输入: num = “1432219”, k = 3
输出: “1219”
解释: 移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219。
示例 2 :
输入: num = “10200”, k = 1
输出: “200”
解释: 移掉首位的 1 剩下的数字为 200. 注意输出不能有任何前导零。
示例 3 :
输入: num = “10”, k = 2
输出: “0”
解释: 从原数字移除所有的数字,剩余为空就是0。
public static String removeKdigits(String num, int k) {
if(num.length()==k) {
return "0";
}
//思路,从左到右,找第一个比后面大的字符,删除,清零,k次扫描。
StringBuffer sb=new StringBuffer();
for(int i=0;i<num.length();i++) {
sb.append(num.charAt(i));
}
if(num.length()>k) {
for(int i=0;i<k;i++) {
int index=0;
for(int j=1;j<sb.length() && sb.charAt(j)>=sb.charAt(j-1);j++) {
index=j;
}
sb.delete(index, index+1);
while (sb.length() > 1 && sb.charAt(0) == '0') sb.delete(0, 1);
}
// while (sb.length() > 1 && sb.charAt(0) == '0') sb.delete(0, 1);
}
return sb.toString();
}
5. 给定一个正整数 n,你可以做如下操作:
- 如果 n 是偶数,则用 n / 2替换 n。
- 如果 n 是奇数,则可以用 n + 1或n - 1替换 n。
n 变为 1 所需的最小替换次数是多少?
示例 1:
输入:
8
输出:
3
解释:
8 -> 4 -> 2 -> 1
示例 2:
输入:
7
输出:
4
解释:
7 -> 8 -> 4 -> 2 -> 1
或
7 -> 6 -> 3 -> 2 -> 1
//用位运算,最后一位是0直接右移,最后两位都是1,且该数不是3是,就选择+1,否则就选择-1,直到该数变成1,为防止越界,把n变成长整型 c代码
public static int integerReplacement(int n) {
int count=0;
long temp=n;
while(temp!=1) {
if((temp&3)==3&&temp!=3) {
temp++;
}else if((temp&1)==1) {
temp--;
}else {
temp=temp/2;
}
count++;
}
return count;
}
6. 给定一个字符串S,检查是否能重新排布其中的字母,使得两相邻的字符不同。
若可行,输出任意可行的结果。若不可行,返回空字符串。
示例 1:
输入: S = “aab”
输出: “aba”
示例 2:
输入: S = “aaab”
输出: “”
/**
* 更高效的算法,思路如下:
* 找出出现频率最高的char,然后要把他们分隔开, 隔一个slot插值
* 对于其他所有的剩余字符,也是隔一个插入,因为长度小于一半,所以肯定不会重复
*/
public static String reorganizeString(String s){
if (s == null || s.length() == 0) {
return "";
}
//词频统计
int[] count = new int[26];
for (char c : s.toCharArray()) {
count[c - 'a']++;
}
//寻找最大频率的字母
int maxCount = 0;
char letter = 0;
for (int i = 0; i < 26; i++) {
if (maxCount < count[i]) {
maxCount = count[i];
letter = (char) ('a' + i);
}
}
//如果最大频率大于一半+1,则无法完成任务
if (maxCount > (1 + s.length()) / 2) {
return "";
}
//结果集
char[] res = new char[s.length()];
//index 维护下一个应该插入的位置
//隔空插入最大频率字母
int index = insert(count, res, 0, letter);
//插入其他字母
for (int i = 0; i < 26; i++) {
index = insert(count, res, index, (char)('a' + i));
}
return new String(res);
}
private static int insert(int[] count, char[] res, int index, char letter) {
int i = letter - 'a';
while (count[i] > 0) {
//因为index大于res长度的情况是之前从0开始间隔2插入了频率最高的字符,
// 所以这里应该是从0和2之间的间隔开始
if (index >= res.length) {
index = 1;
}
res[index] = letter;
count[i]--;
index += 2;
}
//返回下一个能插入的位置
return index;
}