一、数组的增删改查
1.数组的初始化
/**
* 初始化数组
*/
public static void init() {
int[] a1 = new int[]{1, 2, 3, 4, 5};
int[] a2 = {1, 2, 3, 4, 5};
int[] a3 = new int[5];
for (int index = 0; index < a3.length; index++) {
a3[index] = index + 1;
}
}
2.根据索引查找
/**
* 根据索引查找
* @param array 数组
* @param size 数组大小
* @param index 要查找的目标元素的索引
* @return 查找到的元素
* @throws Exception 异常
*/
public static int findByIndex(int[] array, int size, int index) throws Exception {
if (index >= size || index < 0) {
throw new Exception("index不合法!");
}
return array[index];
}
3.根据元素查找
/**
* 根据元素查找
* @param array 数组
* @param size 数组大小
* @param item 要查找的目标元素
* @return 查找到的元素
* @throws Exception 异常
*/
public static int findByItem(int[] array, int size, int item) throws Exception {
for (int index = 0; index < size; index++) {
if (array[index] == item) {
return index;
}
}
return -1;
}
4.在指定位置插入
/**
* 在指定位置插入
* @param array 数组
* @param size 数组大小
* @param item 要插入的元素
* @param index 插入的位置
* @throws Exception 异常
*/
public static void addByIndex(int[] array, int size, int item, int index) throws Exception {
if (size > array.length - 1) {
throw new Exception("数组已满,不能再插入!");
}
if (index > array.length - 1 || index < 0) {
throw new Exception("index不合法!");
}
for (int i = size - 1; i >= index; i--) {
array[i + 1] = array[i];
}
array[index] = item;
size++;
}
5.有序数组中插入元素
/**
* 有序数组中插入元素
* @param array 有序数组
* @param size 数组中已有元素的个数
* @param item 要插入的数据
* @throws Exception 异常
*/
public static void addItemSequence(int[] array, int size, int item) throws Exception {
if (size > array.length - 1) {
throw new Exception("数组已满,不能再插入!");
}
if (size < 0) {
throw new Exception("size输入不合法!");
}
int key = size;
for (int i = 0; i < size; i++) {
if (item < array[i]) {
key = i;
break;
}
}
for (int i = size - 1; i >= key; i--) {
array[i + 1] = array[i];
}
array[key] = item;
size++;
}
6.根据索引删除
/**
* 根据索引删除
* @param array 数组
* @param size 数组已有元素个数
* @param index 索引
* @throws Exception 异常
*/
public static void removeByIndex(int[] array, int size, int index) throws Exception {
if (size < 0) {
throw new Exception("size输入不合法!");
}
if (size == 0) {
return;
}
if (index > array.length - 1 || index < 0 || index >= size) {
throw new Exception("index输入不合法!");
}
for (int i = index; i < size - 1; i++) {
array[i] = array[i + 1];
}
array[size - 1] = 0;
}
7.根据元素删除
/**
* 根据元素删除
* @param array 数组
* @param size 数组已有元素个数
* @param item 索引
* @throws Exception 异常
*/
public static void removeByItem(int[] array, int size, int item) throws Exception {
if (size < 0) {
throw new Exception("size输入不合法!");
}
if (size == 0) {
return;
}
int index = -1;
for (int i = 0; i < size; i++) {
if (array[i] == item) {
index = i;
break;
}
}
if (index == -1) {
return;
}
removeByIndex(array, size, index);
}
二、数组的合并
案例
给你两个按⾮递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数⽬。 请你合并 nums2 到 nums1 中,使合并后的数组同样按非递减顺序排列。 注意:最终,合并后数组不应由函数返回,⽽是存储在数组 nums1 中。为了应对这种情况,nums1 的初始⻓度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的⻓度为 n 。 例⼦1: 输⼊:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3 输出:[1,2,2,3,5,6]
解释:需要合并 [1,2,3] 和 [2,5,6] 。
合并结果是 [1,2,2,3,5,6]。\
方法一:直接在num1的m索引处往后面加,加完再排序
public static void merge1(int[] a1, int[] a2, int m, int n) {
for (int index = m - n; index < m; index++) {
a1[index] = a2[index - n];
}
Arrays.sort(a1);
}
方法二:一边合并一边排序,最大值应该合并后的最大索引的位置。
public static void merge2(int[] a1, int[] a2, int m, int n) {
int length = m - 1;
int len1 = m - n - 1;
int len2 = n - 1;
while (len1 >= 0 && len2 >= 0) {
if (a1[len1] >= a2[len2]) {
a1[length--] = a1[len1--];
} else {
a1[length--] = a2[len2--];
}
}
while (len2 >= 0) {
a1[length--] = a2[len2--];
}
}
三、字符串替换
案例
给定字符串"we are Chinese!",将其中空格替换成%#$
方法一:新创建一个字符串,一边遍历旧的字符串一边判断是否是空格,如果是空格就在原来的基础上加%#$
public static String replace1(String str) {
if (str == null) {
return null;
}
String strNew = "";
char[] chars = str.toCharArray();
for (char aChar : chars) {
if (aChar == ' ') {
strNew += "%#$";
} else {
strNew += aChar;
}
}
return strNew;
}
方法二:先统计空格的个数,每替换一个空格字符串的长度就加2,新的字符串的长度=老的字符串长度+空格数量*2。定义两个指针,一个指向新字符串末尾,一个指向老字符串末尾,从后往前遍历,如果是空格就替换,指针前移三位。
public static String replace2(String str) {
if (str == null) {
return null;
}
int count = 0;
for (int index = 0;index < str.length();index++) {
char c = str.charAt(index);
if (c == ' ') {
count++;
}
}
int oldLength = str.length() - 1;
int newLength = str.length() + 2 * count - 1;
StringBuilder stringBuilder = new StringBuilder(str);
stringBuilder.setLength(newLength + 1);
while ((oldLength >= 0 && newLength > oldLength)) {
char c = str.charAt(oldLength);
if (c == ' ') {
stringBuilder.setCharAt(newLength--, '$');
stringBuilder.setCharAt(newLength--, '#');
stringBuilder.setCharAt(newLength--, '%');
} else {
stringBuilder.setCharAt(newLength--, c);
}
oldLength--;
}
return stringBuilder.toString();
}
四、删除数组中指定元素
案例
给定一个数组,删除数组中指定元素,并返回新数组的长度 如数组{1, 2, 3, 4, 5},删除3,返回4
方法一:不新开辟空间,新的数组有效长度以统计的个数为准,大于统计的个数索引后面的元素不考虑。例如统计的新数组有效长度是5,那么4索引位置以后的元素作废。
public static int remove1(int[] nums, int val) {
int count = 0;
for (int index = 0; index < nums.length; index++) {
if (nums[index] != val) {
nums[count++] = nums[index];
}
}
return count;
}
方法二:新创建一个数组,循环判断是否等于给定元素,不等于就放入新数组中。
public static int length(int[] nums, int num) {
int count = 0;
for (int index = 0; index < nums.length; index++) {
if (nums[index] == num) {
count++;
}
}
int oldLength = nums.length - 1;
int len = nums.length - count;
int[] newNum = new int[len];
while (oldLength > 0) {
if (nums[oldLength] != num) {
newNum[--len] = nums[oldLength];
}
oldLength--;
}
return newNum.length;
}
五、删除有序数组中重复元素,使每个元素只出现一次
案例
给定数组{1, 2, 2, 3, 3},删除后返回{1, 2, 3}
public static int remove2(int[] array) {
int length = array.length;
int j = 1;
for (int index = 1; index < length; index++) {
if (array[index] != array[j - 1]) {
array[j] = array[index];
j++;
}
}
return j;
}
六、元素奇数偶数移动问题
案例
给定数组{1,2, 3, 4},输出{2,4,1,3},偶数放前面,奇数放后面,输出{4,2,1,3}和{4,2,3,1}也是可以的,元素顺序不影响,只要偶数在一起,奇数在一起。
方法一:暴力破解,遍历两次,第一次获取是偶数的元素,第二次获取是奇数的元素,
public static int[] order1(int[] array) {
int[] a = new int[array.length];
int j = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] % 2 == 0) {
a[j] = array[i];
j++;
}
}
for (int i = 0; i < array.length; i++) {
if (array[i] % 2 != 0) {
a[j] = array[i];
j++;
}
}
return a;
}
方法二:双指针遍历,如果是偶数就把偶数放在前面,和他后面的元素交换位置
public static int[] order2(int[] array) {
int i = 0;
int j = array.length;
for (int index = 0; index < j; index++) {
if (array[index] % 2 == 0) {
int temp = array[i];
array[i] = array[index];
array[index] = temp;
i++;
}
}
return array;
}
七、数组移动
案例
给你⼀个数组,将数组中的元素向右轮转 k 个位置,其中 k 是⾮负数。 例如: 输⼊: nums = [1,2,3,4,5,6,7], k = 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5,6,7,1,2,3,4] \
解答:先把整个数组翻转,然后从0到k处翻转,然后从k到数组长度翻转
public static void reverse(int[] array, int start, int end) {
while (start < end) {
int temp = array[start];
array[start] = array[end];
array[end] = temp;
start++;
end--;
}
}
public static void rotate(int[] array, int k) {
reverse(array, 0, array.length - 1);
reverse(array, 0, k - 1);
reverse(array, k, array.length - 1);
}
八、数组加一
案例
给定正整数数组,实现数组的整数值加一。给出数组{1,2,3},输出{1,2,4};输入{9,9,9},输出{1,0,0,0}
方法一:从末位开始往前面计算,判断是否需要进位,进位就把当前位置置0,否则退出循环。如果一直到最后一位都需要进位,那么需要申请一个原来数组长度+1的数组进行存储。
public static int[] add1(int[] array) {
int length = array.length - 1;
int newLength = array.length;
int last = array[length];
int result = last + 1;
if (result == 10) {
while (length > 0 && result == 10) {
array[length] = 0;
length--;
result = array[length] + 1;
}
array[length] = array[length] + 1;
if (array[length] == 10) {
array[length] = 1;
}
} else {
array[length] = result;
}
if (result == 10) {
int[] arr = new int[newLength + 1];
arr[0] = 1;
return arr;
}
return array;
}
方法二:从后往前循环遍历,给每个位置加一,再对10取余,不等于0直接返回。
public static int[] add2(int[] array) {
for (int index = array.length - 1; index >= 0; index--) {
array[index]++;
array[index] %= 10;
if (array[index] != 0) {
return array;
}
}
int[] arr = new int[array.length + 1];
arr[0] = 1;
return arr;
}
九、数组和指定数字相加
案例
给出数组{1,2,3,4},和数组1234相加,输出{2,4,6,8};给出数组{9,9,9,9}和数字9999,输出{1,9,9,9,8}
解法:
将数组转换成数字,和数字相加,再转换成数组
public static int[] add4(int[] array, int val) {
int count = 0;
for (int index = array.length - 1; index >= 0; index--) {
int first = array[index];
count = count + first * (int)Math.pow(10, array.length - index - 1);
}
int result = count + val;
int resultNum = result;
int n = 0;
while (result / 10 > 0) {
result = result / 10;
n++;
}
n++;
int[] arr = new int[n];
for (int index = n - 1; index >= 0; index--) {
arr[index] = resultNum % 10;
resultNum = resultNum / 10;
}
return arr;
}
public static int power(int num, int power) {
if (power == 0) {
return 1;
}
int result = num;
for (int index = 1;index < power; index++) {
result = result * result;
}
return result;
}
十、字符串相加
案例
例如"123"加"456",输出"579"
这里还是采用双指针的思想,从低位开始加
private static String add1(String num1, String num2) {
int i = num1.length() - 1;
int j = num2.length() - 1;
int add = 0;
StringBuilder stringBuilder = new StringBuilder();
while (i >= 0 || j >= 0 || add != 0) {
int x = 0;
int y = 0;
if (i >= 0) {
x = num1.charAt(i) - '0';
}
if (j >= 0) {
y = num2.charAt(j) - '0';
}
int result = x + y + add;
stringBuilder.append(result % 10);
add = result / 10;
i--;
j--;
}
stringBuilder.reverse();
return stringBuilder.toString();
}
案例:
变形题:二进制字符串加法,原理相同,只不过是逢二进一
private static String add2(String num1, String num2) {
int i = num1.length() - 1;
int j = num2.length() - 1;
int add = 0;
StringBuilder stringBuilder = new StringBuilder();
while (i >= 0 || j >= 0 || add != 0) {
int x = 0;
int y = 0;
if (i >= 0) {
x = num1.charAt(i) - '0';
}
if (j >= 0) {
y = num2.charAt(j) - '0';
}
int result = x + y + add;
stringBuilder.append(result % 2);
add = result / 2;
i--;
j--;
}
stringBuilder.reverse();
return stringBuilder.toString();
}
十一、找出数组中出现次数超过一半的数字
案例
给出数组{1,2,1,2,1},输出1,如果没有次数最多的数字则输出0,如{1,1,2,2},输出0
方法一:排序找中位数,中位数一定是次数最多的,如果没有超过一半那就是没有
public static int overHalf1(int[] nums) {
int length = nums.length;
for (int i = 0; i < length; i++) {
for (int j = 0; j < length - i - 1; j++) {
if (nums[j] > nums[j + 1]) {
int temp = nums[j];
nums[j] = nums[j + 1];
nums[j + 1] = temp;
}
}
}
int num = 0;
if (length % 2 == 0) {
num = (nums[length / 2 - 1] + nums[length / 2]) / 2;
} else {
num = (nums[length / 2]);
}
int count = 0;
for (int index = 0; index < length; index++) {
if (nums[index] == num) {
count++;
}
}
if (count > length / 2) {
return num;
}
return 0;
}
方法二:利用map,key存数组,value存出现的次数
public static int overHalf2(int[] nums) {
Map<Integer, Integer> map = new LinkedHashMap<>();
int length = nums.length;
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
if (map.get(num) > (length / 2)) {
return num;
}
}
return 0;
}
方法三:计数法,设置初始出现次数为1,从第二个元素开始遍历,如果下一个元素还是这个元素就给次数+1,否则就减一。
public static int overHalf3(int[] nums) {
int length = nums.length;
int result = nums[0];
int times = 1;
for (int index = 1; index < length; index++) {
if (times == 0) {
result = nums[index];
times++;
continue;
}
if (nums[index] == result) {
times++;
} else {
times--;
}
}
times = 0;
for (int num : nums) {
if (num == result) {
times++;
}
}
if (times > (length / 2)) {
return result;
}
return 0;
}
十二、找出数组中只出现一次的数字
例如{1,2,2,3,3},输出1
方法一:两次for循环搞定,设置计数器初始值为1,如果出现重复值就加一,一次循环结束判断计数器是否还是1,如果还是1就是要找的数。
public static int oneTimes1(int[] nums) {
int length = nums.length;
for (int i = 0; i < length; i++) {
int times = 1;
int result = nums[i];
for (int j = 0; j < length; j++) {
if (nums[j] == nums[i] && i != j) {
times++;
}
}
if (times == 1) {
return result;
}
}
return 0;
}
方法二:用异或
public static int oneTimes2(int[] nums) {
int result = 0;
for (int num : nums) {
result ^= num;
}
return result;
}