重构字符串
给定一个字符串S
,检查是否能重新排布其中的字母,使得两相邻的字符不同。
若可行,输出任意可行的结果。若不可行,返回空字符串。
示例 1:
输入: S = "aab"
输出: "aba"
示例 2:
输入: S = "aaab"
输出: ""
java
1.桶排序加贪心算法分配
桶排序的基本思想就是统计+再分配:
所以之前先遍历一遍字符串: 使用int[ 26 ] 的数组来表示26个字母,0表示a,1表示b…
char[] c = S.toCharArray();
int[] tong = new int[26];
int length = S.length();
for (int i = 0; i < length; i++) {
tong[c[i] - 'a']++;
}
若以 aaaabbbcc举例:
得到字符串的统计: {4, 3, 2, 0, 0, 0, 0, … 0};
那遍历我们的桶, 按照贪心算法的思想, 优先排序字符数量最多的字符,声明长度为length的char数组,然后隔一个位置插入一个最多的字符,
然后再用剩余字符插入留下的空位,可得到最优化的解答:
char[] res = new char[length];
int index = 0;
while (tong[alphabet]-- > 0) {
res[index] = (char) (alphabet + 'a');
index += 2;
}
for (int i = 0; i < tong.length; i++) {
while (tong[i]-- > 0) {
if (index >= res.length) {
index = 1;
}
res[index] = (char) (i + 'a');
index += 2;
}
}
return new String(res);
但是当最多的字符过多( 超过原来字符长度 / 2 的时候, 则一定不能组成要求 , 直接返回 " " );
int max = 0, alphabet = 0, threshold = (length + 1) >> 1; // 最后这个是右移一位,相当于/2;
for (int i = 0; i < tong.length; i++) {
if (tong[i] > max) {
max = tong[i];
alphabet = i;
if (max > threshold)
return "";
}
}
完整代码:
class Solution {
public String reorganizeString(String S) {
char[] c = S.toCharArray();
int[] tong = new int[26];
int length = S.length();
for (int i = 0; i < length; i++) {
tong[c[i] - 'a']++;
}
int max = 0, alphabet = 0, threshold = (length + 1) >> 1;
for (int i = 0; i < tong.length; i++) {
if (tong[i] > max) {
max = tong[i];
alphabet = i;
if (max > threshold)
return "";
}
}
char[] res = new char[length];
int index = 0;
while (tong[alphabet]-- > 0) {
res[index] = (char) (alphabet + 'a');
index += 2;
}
for (int i = 0; i < tong.length; i++) {
while (tong[i]-- > 0) {
if (index >= res.length) {
index = 1;
}
res[index] = (char) (i + 'a');
index += 2;
}
}
return new String(res);
}
}
python
贪心算法:
class Solution:
def reorganizeString(self, S: str) -> str:
slen = len(S)
dict1 = {}
for i in S:
if i not in dict1.keys():
dict1[i] = 1
else:
dict1[i] += 1
maxsize = 0
thisChar = "a"
for i in dict1.keys():
if dict1[i]>maxsize:
maxsize = dict1[i]
thisChar = i
if maxsize > slen+1>>1:
return ""
s = []
for i in range(0,slen):
s.append(0)
index = 0
while maxsize>0:
s[index] = thisChar
index+=2
maxsize-=1
dict1.pop(thisChar)
for i in dict1.keys():
while dict1[i]>0:
if index >= len(s):
index = 1
s[index] = i
index+=2
dict1[i]-=1
s1 = ""
for i in range(0,slen):
s1+=s[i]
return s1
在排序数组中查找元素的第一个和最后一个位置
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
示例 1:
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
示例 2:
输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]
示例 3:
输入:nums = [], target = 0
输出:[-1,-1]
java
1.顺序遍历查找
找到了以后for循环查找下一个元素,若有,指针后移,若没有,返回当前位置
class Solution {
public int[] searchRange(int[] nums, int target) {
if(nums.length==1&&target==nums[0])return new int[]{0,0};
for(int i =0 ;i<nums.length;i++){
if(nums[i]==target){
int j = i;
while (j<nums.length){
if(nums[i]==nums[j]){
j++;
}else{
return new int[]{i,j-1};
}
}return new int[]{i,j-1};
}
}
return new int[]{-1,-1};
}
}
2.二分查找:
题目进阶要求时间复杂度为o(log n)
很明显为二分查找: 从中间位置查找,如果大于该数,则向右边继续查找,小于向左边查找减小查找时间
class Solution {
public int[] searchRange(int[] nums, int target) {
int leftIdx = bS(nums, target, true);
int rightIdx = bS(nums, target, false) - 1;
if (leftIdx <= rightIdx && rightIdx < nums.length && nums[leftIdx] == target && nums[rightIdx] == target) {
return new int[]{leftIdx, rightIdx};
}
return new int[]{-1, -1};
}
public int bS(int[] nums, int target, boolean lower) {
int left = 0, right = nums.length - 1, ans = nums.length;
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] > target || (lower && nums[mid] >= target)) {
right = mid - 1;
ans = mid;
} else {
left = mid + 1;
}
}
return ans;
}
}
python
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
for i in range(len(nums)):
if nums[i] == target:
j = i + 1
while j < len(nums) and nums[j] == target: j+=1
return [i, j-1]
return [-1, -1]