题目集合出处:LeetCode 网址:https://leetcode-cn.com/explore/orignial/card/all-about-array/230/define-with-good-care/948/
借此集合重新梳理一下有关数组的相关操作ヾ(◍°∇°◍)ノ゙
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入:[0,1,0,3,12]
输出:[1,3,12,0,0]
说明:
思路:设置两个指针lastIndex和temp,由temp从后向前遍历,遇到为零的元素时停止,并将temp到lastIndex之间的元素均向前移动一个单位,结束后,将末尾元素置零,并将lastIndex向前移动一个单位。重复以上操作直至temp=0;
class Solution {
public void moveZeroes(int[] nums) {
int lastIndex=nums.length-1;
int temp=nums.length-1;
int count=0;
while(temp>=0) {
if(nums[temp]==0) {
count=lastIndex-temp;
for(int i=temp;i
给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例 1:
给定 nums = [3,2,2,3], val = 3,
函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。
你不需要考虑数组中超出新长度后面的元素。
示例 2:
给定 nums = [0,1,2,2,3,0,4,2], val = 2, 函数应该返回新的长度5
并且 nums 中的前五个元素为0,1,3,0,4
注意这五个元素可为任意顺序。 你不需要考虑数组中超出新长度后面的元素。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
int len = removeElement(nums, val);
// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}
思路:从前向后遍历,遇到待删元素则不计入数组
8ms
class Solution {
public int removeElement(int[] a, int val) {
int sum=0;
for (int i = 0;i
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
示例 1:
给定数组 nums = [1,1,2],
函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 [1,2]
你不需要考虑数组中超出新长度后面的元素。
示例 2:
给定 nums = [0,0,1,1,1,2,2,3,3,4],
函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为
[0,1,2,3,4]
你不需要考虑数组中超出新长度后面的元素。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);
// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}
思路:用指针i来记录最终返回数组元素个数,用j遍历数组。如遇重复项则不计入i中。待后续优化ヾ(◍°∇°◍)ノ゙【12ms】
class Solution {
public int removeDuplicates(int[] nums) {
if(nums.length==0)
return 0;
int i=0,j;
for(j=1;j
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
示例 1:
给定 nums = [1,1,1,2,2,3], 函数应返回新长度 length =5
, 并且原数组的前五个元素被修改为1, 1, 2, 2,3
你不需要考虑数组中超出新长度后面的元素。
示例 2:
给定 nums = [0,0,1,1,1,1,2,3,3], 函数应返回新长度 length =7
, 并且原数组的前五个元素被修改为0
, 0, 1, 1, 2, 3, 3 。 你不需要考虑数组中超出新长度后面的元素。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);
// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}
思路:思路同上题,由于有新的限制,则设置一个count来记录一个数字出现的次数,初始化为1。当遇到下一个相同数字时+1,如果count<3 则将nums[j]赋于nums[i]。
class Solution {
public int removeDuplicates(int[] nums) {
if(nums.length==0)
return 0;
int i=0,count=1,j;
for(j=1;j
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
注意:
不能使用代码库中的排序函数来解决这道题。
示例:
输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]
进阶:
除了题目原有的解题思路,还可以使用各大排序算法进行排序
这里使用的是选择排序
class Solution {
public static void sortColors(int[]nums) {
int i=0;
int j=0;
int min=nums[0];
int minIndex=0;
for(i=0;i
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:
输入: [3,2,1,5,6,4] 和
k = 2
输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6] 和
k = 4
输出: 4
说明:
你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。
class Solution {
public int findKthLargest(int[] nums, int k) {
Arrays.sort(nums);
return nums[nums.length-k];
}
}
这里偷懒了直接使用的排序函数,用快排更优ヾ(◍°∇°◍)ノ゙
给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。
说明:
class Solution {
public void merge(int[] nums1, int m, int[] nums2, int n) {
int i=0;//nums1
int j=0;//nums2
for(i=m;i= last)
return;
int i = first, j = last;
int pivot = nums[i];// 选取第一个元素作为基准元素
while (i < j) {
while (i < j && nums[j] > pivot) { // 从右往左找比基准元素小的元素
j--;
}
if (i < j) {
nums[i++] = nums[j];
}
while (i < j && nums[i] <= pivot) { // 从左往右找比基准元素大的元素
i++;
}
if (i < j) {
nums[j--] = nums[i];
}
}
nums[i] = pivot;
quickSort(nums, first, i - 1);
quickSort(nums, i + 1, last);
}
}
【另:尾插法:选取两数组中最大元素从后往前放置(nums1有足够大的空间,从k=m+n-1开始)】
给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。
函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。
说明:
示例:
输入: numbers = [2, 7, 11, 15], target = 9
输出: [1,2]
解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。
思路:设置双指针,一个从左向右遍历,一个从右向左。如果两数相加等于target则输出数组,如果大于target则将右指针向前移动,减少相加所得数值(此为升序数组)
千万注意题目中的index1和index2不是从零开始的(以下是由着从0开始编写的,故而新生成数组时两指针均+1来确保答案正确ヾ(◍°∇°◍)ノ゙)
class Solution {
public int[] twoSum(int[] numbers, int target) {
int l=0;
int r=numbers.length-1;
while(ltarget)
r--;//减少数值
else
l++;//增大数值
}
return numbers;
}
}
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。
示例 1:
输入: "A man, a plan, a canal: Panama"
输出: true
示例 2:
输入: "race a car"
输出: false
思路1:将字符串中除了字母和数字外的字符去除,统一转成小写/大写模式,再使用双指针进行一一比对。错误则输出false
【使用java中的replaceAll方法】
class Solution {
public boolean isPalindrome(String s) {
s=s.replaceAll("[^a-zA-Z0-9]", "");//保留字母和数字
s=s.toLowerCase();
char[]c=s.toCharArray();
int i=0,j=s.length()-1;
while(i<=j) {
if(c[i]!=c[j])
return false;
i++;
j--;
}
return true;
}
}
思路2:将字符串中除了字母和数字外的字符去除,统一转成大写/小写模式,再将字符串反转,若反转后字符串与原字符串不相等,则输出false
编写一个函数,以字符串作为输入,反转该字符串中的元音字母。
示例 1:
输入: "hello"
输出: "holle"
示例 2:
输入: "leetcode"
输出: "leotcede"
说明:
元音字母不包含字母"y"。
首先要知道元音字母有:aeiou!
思路:双索引
class Solution {
public String reverseVowels(String s) {
if(s==""||s==null)
return s;
char c[]=s.toCharArray();//变为数组
int i=0,j=s.length()-1;
while(i
给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。
class Solution {
public int maxArea(int[] height) {
int maxare=0;//最大水量
int l=0,r=height.length-1;
while(l
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。
示例:
输入:s = 7, nums = [2,3,1,2,4,3]
输出: 2 解释: 子数组[4,3]
是该条件下的长度最小的连续子数组。
class Solution {
public static int minSubArrayLen(int s,int[]nums) {
int left=0,right=-1;
int sum=0;
int min=nums.length+1;
while(left=s) {
min=Math.min(min, right-left+1);
}
}
if(min==nums.length+1)
return 0;
return min;
}
}
官方解题思想:
要求是连续子数组,所以我们必须定义 i,j两个指针,i 向前遍历,j 向后遍历,相当与一个滑块,这样所有的子数组都会在 [i...j] 中出现,如果 nums[i..j] 的和小于目标值 s,那么j向后移一位,再次比较,直到大于目标值 s 之后,i 向前移动一位,缩小数组的长度。遍历到i到数组的最末端,就算结束了,如果不存在符合条件的就返回 0。