O1复杂度下数组内元素移动问题
一、同一个数组里的移动
两种相对条件下的数组内元素移位
1、奇数在前,偶数在后。
//采用冒泡实现该算法,时间复杂度O(N2),空间复杂度O(n1),设置优化flag位。
public static void main(String[] args) {
int[] nums = new int[]{9,9,14,1,2,7,12,8,14,20};
int n = nums.length;
int l = 0, r = l + 1;
while (l < n){
if(nums[l]%2 == 0){
while (r < n){
if (nums[r]%2 != 0){
//优化 采用循环前移降低时间复杂度
// flip(nums,l,r);
// flip(nums, l+1,r);
for (int i = r; i > l; i--) {
swap(nums, i-1, i);
}
l++;
}
r++;
}
break;
}
l++;
r++;
}
}
public static void swap(int[] nums, int l, int r){
int t = 0;
t = nums[l];
nums[l] = nums[r];
nums[r] = t;
}
2、0在前,1在后
//采用直接置位,复杂度均为O1
public static int[] remove0(int[] nums){
int n = nums.length;
int l = n-1, r = n-1;
while (l >= 0){
if(nums[r] == 0){
while (l > 0){
l--;
if(nums[l] != 0){
nums[r] = nums[l];
r--;
}
}
break;
}
l--;
r--;
}
for (int i = 0; i <= r; i++) {
nums[i] = 0;
}
return nums;
}
3、数字在前,字母在后 (招银一面)
public static String removeChacters(String string){
char[] chars = string.toCharArray();
int n = chars.length;
int l = 0, r = l+1;
while (l < n)
{
if(!Character.isDigit(chars[l])){
while (r < n){
if(Character.isDigit(chars[r])){
for (int i = r; i > l; i--) {
swap(chars, i, i-1);
}
l++;
}
r++;
}
break;
}
l++;
r++;
}
return chars.toString();
}
public static void swap(char[] chars, int i, int j){
char temp = ' ';
temp =chars[i];
chars[i] = chars[j];
chars[j] = temp;
}
移动数组内元素,条件a在前,条件b在后,且保持元素间相对位置不变。
4、时间复杂度优化:将一个数循环移位的优化
public static void moveKplace(int[] nums, int k){
int n = nums.length;
k = k % n;
flip(nums,0, nums.length-1);
flip(nums, n - k, nums.length-1);
}
public static void flip(int[] nums,int i, int j){
while (i < j){
swap(nums, i, j);
i++;
j--;
}
}
数组内关于重复元素的操作
1、找不重复数(无序约束)
针对一个数组中,只有一个不重复数
public static int singleNumber(int[] nums){
int n = nums.length;
Arrays.sort(nums);
int l = 0, r = l+1;
while (r < n){
if(nums[l] == nums[r]){
while (r < n && nums[r] == nums[l])
r++;
}
if(r-l == 1){
return nums[l];
}
else {
l = r;
r += 1;
}
}
if(l >= n)
return -1;
else
return nums[l];
}
1.2 找第一个不重复数、字符
public static char firstUniqChar(String s) {
int n = s.length();
if(n == 0) return ' ';
char[] nums = s.toCharArray();
if(n == 1) return nums[0];
HashMap<Character, Integer> map = new HashMap<>();
for(int i = 0; i<n;i++){
map.put(nums[i], map.getOrDefault(nums[i], 0)+1);
}
for(int i = 0; i< n;i++){
if(map.get(nums[i]) == 1)
return nums[i];
}
return ' ';
}
2、消除重复元素
针对于数组内只有一个不重复数字!(代码存疑!!!!)
public static void removeRepeat(int[] nums){
int n = nums.length;
Arrays.sort(nums);
int l = 0, r = l+1, index = 1;
while (r < n){
if(nums[l] == nums[r]){
while (r < n && nums[r] == nums[l])
r++;
if(r < n){
nums[index] = nums[r];
index++;
}
else
break;
}
l = r;
r += 1;
}
for (int i = index; i < n; i++) {
nums[i] = 0;
}
}
2.1 消除重复数(重复数字只保留一个)
相当于python中list(set(list))
函数
public static int[] singleNumbers(int[] nums) {
int n = nums.length;
Arrays.sort(nums);
int l = 0;
for (int i = 1; i < n; i++) {
if(nums[l] != nums[i]){
l++;
nums[l] = nums[i];
}
}
int len = l+1;
int[] num = new int[l+1];
for (int i = 0; i < l+1; i++) {
num[i] = nums[i];
}
return num;
}
2.2 消除重复数(只保留两个不重复只出现一次的数字)
int ret = 0;
for (int n : nums) {
ret ^= n;
}
int div = 1;
while ((div & ret) == 0) {
div <<= 1;
}
int a = 0, b = 0;
for (int n : nums) {
if ((div & n) != 0) {
a ^= n;
} else {
b ^= n;
}
}
return new int[]{a, b};
3、找众数
如果将数组 nums 中的所有元素按照单调递增或单调递减的顺序排序,那么下标为n/2
的元素(下标从 0 开始)一定是众数。
public static int majorityElement(int[] nums){
Arrays.sort(nums);
int n = nums.length;
return nums[n/2];
}
二、两个数组移动为一个
两个有序数组合并为一个有序数组
1、合并两个有序数组到第一个无限大的数组之中,且保持有序
public static void moveTonums(int m, int n, int[] nums1, int[] nums2){
int k = nums1.length - 1;
int l1 = m-1, l2 = n-1;
while (l1 >= 0 && l2 >= 0){
if(nums1[l1] > nums2[l2]){
nums1[k] = nums1[l1];
l1--;
}
else if(nums1[l1] < nums2[l2]){
nums1[k] = nums2[l2];
l2--;
}
k--;
}
}