IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> LeetCode-数组&字符串 -> 正文阅读

[数据结构与算法]LeetCode-数组&字符串

数组&字符串

9 回文数

public boolean isPalindrome(int x) {
if(x < 0) return false;
String str = Integer.toString(x);
char[] charArr = str.toCharArray();
for(int i = 0; i < charArr.length/2; i++){
if(charArr[i] != charArr[charArr.length-1-i]){
return false;
}
}
return true;
}
方法2:
public boolean isPalindrome(int x) {
if(x<0) return false;
if(x % 10 == 0 && x != 0) return false; //末位是0,不可能是回文数
int halfReserve = 0;
while((x - halfReserve) > 0){
halfReserve = halfReserve*10 + x%10;
x = x/10;
}
System.out.println(halfReserve+" "+ x);
if(x == halfReserve) return true;
if(x == halfReserve/10) return true;//121
return false;
}

26 从排序数组中删除重复项

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

很简单,直接上代码:
class Solution {
public int removeDuplicates(int[] nums) {
int index=0;
for(int i =1 ; i < nums.length ; i++){
if ( nums[i] != nums[index]){
index ++;
nums[index] = nums[i];
}
}
return ++index;
}
}

27 移除元素

原地移除所有=val的值,返回新数组的长度[3,2,2,3] 3 --> [2,2]
public int removeElement(int[] nums, int val) {
if(nums == null || nums.length == 0) return 0;
int index = 0;
for(int i = 0; i < nums.length; i++){
if(nums[i] != val){
nums[index] = nums[i];
index++;
}
}
return index;
}

mid 80 从排序数组中删除重复项II

/*

  • 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。
    */
    扩展 最多出现n次 repeat
    public int removeDuplicatesII(int[] nums) {
    if(nums == null || nums.length == 0) return 0;
    int repeat = 2;
    int slow = repeat;
    for(int fast = repeat; fast < nums.length; fast++){
    if(nums[fast] != nums[slow-repeat]){
    nums[slow] = nums[fast];
    slow++;
    }
    }
    return slow;
    }

public class DeleteRepeatedItemsII {
public static void main(String[] args) {
DeleteRepeatedItemsII d = new DeleteRepeatedItemsII();
int[] nums = {0,0,1,1,1,1,2,3,3,4};
int length = d.removeDuplicates(nums);
for(int i = 0; i < length; i++) {
System.out.println(nums[i]);
}
}
public int removeDuplicates(int[] nums) {
if(nums.length == 0 || nums == null) return 0;
int i = 1;

	for(int j = 2; j < nums.length; j++) {
		
		if(nums[j] != nums[i-1]) {
				i += 1;
    			nums[i] = nums[j];	
		}
	}
	return i+1;
}

}

mid-旋转数组

给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
先将数组的前len-k个元素反转,后k个元素反转,然后再将整个数组反转。注意先让k对len取模。
class Solution {
public void rotate(int[] nums, int k) {
int len = nums.length;
k = k%len;
if(len<2||k==0)return;
swap(nums, 0, len-k-1);
swap(nums, len-k, len-1);
swap(nums, 0, len-1);
}
public void swap(int[] nums, int left, int right){
while(left<right){
int temp = nums[left];
nums[left] = nums[right];
nums[right] = temp;
left++;
right–;
}
}
}

存在重复元素

给定一个整数数组,判断是否存在重复元素。
如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。

方案一:利用HashSet。
class Solution {
public boolean containsDuplicate(int[] nums) {
int len = nums.length;
if(len<2)return false;
HashSet hashSet = new HashSet<>();
for(int num:nums)
if(!hashSet.add(num))return true;
return false;
}
}
方案二:利用Arrays.sort()方法先对数组进行排序,然后判断。
class Solution {
public boolean containsDuplicate(int[] nums) {
int len = nums.length;
if(len<2)return false;
Arrays.sort(nums);
for(int i=0;i+1<len;i++){
if(nums[i]==nums[i+1])return true;
}
return false;
}
}

136 只出现一次的数字 位运算

给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

异或,出现偶数次的元素会被清零,于是留下来的就是那个只出现一次的数字。
public int singleNumber(int[] nums) {
int res = 0;
for(int i = 0; i < nums.length; i++){
res = res ^ nums[i];
}
return res;
}

137 只出现一次的数字II

给你一个整数数组 nums ,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。
方法1:map
执行用时:5 ms, 在所有 Java 提交中击败了30.98%的用户
内存消耗:41 MB, 在所有 Java 提交中击败了18.70%的用户
public int singleNumberII(int[] nums) {
Map<Integer,Integer> map = new HashMap<Integer, Integer>();
int res = 0;
for(int i = 0; i < nums.length; i++){
if(!map.containsKey(nums[i])){
map.put(nums[i],1);

    }else{
        Integer v = map.get(nums[i]);
        map.put(nums[i],v+1);//对于已有的key,新的value会覆盖之前的
    }
}
//用迭代器遍历map
Set entrySet = map.entrySet();
Iterator<Map.Entry> it = entrySet.iterator();
while(it.hasNext()){
    Map.Entry entry = it.next();
    if(entry.getValue().equals(1)){
        res = (Integer)entry.getKey();
    }
}
return res;

}

方法2:位运算

260 只出现一次的数字III 多个出现一次

给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。
public int singleNumberIII(int[] nums) {
Map<Integer,Integer> map = new HashMap<Integer, Integer>();
List reslist = new ArrayList();
for(int i = 0; i < nums.length; i++){
if(!map.containsKey(nums[i])){
map.put(nums[i],1);

    }else{
        Integer v = map.get(nums[i]);
        map.put(nums[i],v+1);
    }
}
Set entrySet = map.entrySet();
Iterator<Map.Entry> it = entrySet.iterator();
while(it.hasNext()){
    Map.Entry entry = it.next();
    if(entry.getValue().equals(1)){
        reslist.add((Integer)entry.getKey());
    }
}
int[] resarr = new int[reslist.size()];
for(int i = 0 ; i < reslist.size(); i++){
    resarr[i] = reslist.get(i);
}
return resarr;

}
位运算:

两个数组的交集 II

给定两个数组,写一个方法来计算它们的交集。
先排序,再比较。
class Solution {
public int[] intersect(int[] nums1, int[] nums2) {
int len1 = nums1.length;
int len2 = nums2.length;
if(len10||len20)return new int[0];
Arrays.sort(nums1);
Arrays.sort(nums2);
List list = new ArrayList<>();
int i=0;
int j=0;
while(i<len1&&j<len2){
if(nums1[i]==nums2[j]){
list.add(nums1[i]);
i++;
j++;
continue;
}
else if(nums1[i]>nums2[j])j++;
else i++;
}
int[] res = new int[list.size()];
for(int k=0;k<list.size();k++)res[k] = list.get(k);
return res;
}
}

加一

给定一个非负整数组成的非空数组,在该数的基础上加一,返回一个新的数组。
最高位数字存放在数组的首位, 数组中每个元素只存储一个数字。
你可以假设除了整数 0 之外,这个整数不会以零开头。

注意进位的处理。
class Solution {
public int[] plusOne(int[] digits) {
int len = digits.length;
if(len==0)return new int[0];
int[] res = new int[len+1];
res[len] = (digits[len-1]+1)%10;
int carry = (digits[len-1]+1)/10;
for(int i=len-2;i>=0;i–){
res[i+1] = (digits[i]+carry)%10;
carry = (digits[i]+carry)/10;
}
res[0] = carry;
if(carry!=0)return res;
int[] res1 = new int[len];
System.arraycopy(res, 1, res1, 0, len);
return res1;
}
}

移动零

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

class Solution {
public void moveZeroes(int[] nums) {
int len = nums.length;
if(len<2)return;
int index = 0;
for(int i=0;i<len;i++){
if(nums[i]!=0)nums[index++] = nums[i];
}
for(int i=index;i<len;i++)nums[i] = 0;
}
}

有效的数独

判断一个 9x9 的数独是否有效。只需要根据以下规则,验证已经填入的数字是否有效即可。

  1. 数字 1-9 在每一行只能出现一次。
  2. 数字 1-9 在每一列只能出现一次。
  3. 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

使用一个二维数组seat保存所有数字的位置,遍历输入的数独,遇见数字则先判断该位置是否与seat中相同数字的位置冲突,若冲突则返回false,否则将当前数字的位置保存至seat中。
class Solution {
public boolean isValidSudoku(char[][] board) {
boolean[][] seat=new boolean[9][27];
for(int i=0;i<9;i++){
for(int j=0;j<9;j++){
if(board[i][j]==‘.’)continue;
int num=board[i][j]-‘0’;
int grid=(i/3)*3+(j/3);
if(seat[num-1][i]||seat[num-1][j+9]||seat[num-1][grid+18])return false;
else{
seat[num-1][i]=true;
seat[num-1][j+9]=true;
seat[num-1][grid+18]=true;
}
}
}
return true;
}
}

mid-旋转图像

给定一个 n × n 的二维矩阵表示一个图像。
将图像顺时针旋转 90 度。
你必须在原地旋转图像。

先按主对角线翻转,再按垂直对称轴翻转。
class Solution {
public void rotate(int[][] matrix) {
int n = matrix.length;
for(int i=0;i<n;i++)
for(int j=0;j<i;j++)
swap(matrix, i, j);
for(int i=0;i<n;i++)swap(matrix, i);
}
public void swap(int[][] matrix, int i, int j){
int temp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = temp;
}
public void swap(int [][] matrix, int i){
int left = 0;
int right = matrix[i].length-1;
while(left<right){
int temp = matrix[i][left];
matrix[i][left] = matrix[i][right];
matrix[i][right] = temp;
left++;
right–;
}
}
}

反转字符串

编写一个函数,其作用是将输入的字符串反转过来。

注意不要想得太复杂了就好。
class Solution {
public String reverseString(String s) {
int len = s.length();
if(len<2)return s;
char[] chars = s.toCharArray();
int left = 0;
int right = len-1;
while(left<right){
char temp = chars[left];
chars[left] = chars[right];
chars[right] = temp;
left++;
right–;
}
return new String(chars);
}
}

mid-反转整数

给定一个 32 位有符号整数,将整数中的数字进行反转。
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [?231, 231 ? 1]。根据这个假设,如果反转后的整数溢出,则返回 0。

不能使用long!!!
class Solution {
public int reverse(int x) {
int res = 0;
while (x != 0){
int temp = res;
res = res * 10 + x % 10;
if (res/10 != temp) return 0;//校验溢出
x /= 10;
}
return res;
}
}

mid-字符串中的第一个唯一字符

给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回-1。

方案一:利用HashMap存下每个字符和其索引的键值对,若该字符重复出现则将HashMap中的key为该字符的value设为-1,最后遍历HashMap中所有的value,找到最小值。
class Solution {
public int firstUniqChar(String s) {
int len = s.length();
if(len0)return -1;
HashMap<Character, Integer> map = new HashMap<>();
for(int i=0;i<len;i++){
char curr = s.charAt(i);
if(map.containsKey(curr))map.put(curr,-1);
else map.put(curr,i);
}
int index = Integer.MAX_VALUE;
Iterator it = map.values().iterator();
while(it.hasNext()){
int i = (int)it.next();
if(i!=-1)index = Math.min(index,i);
}
return index
Integer.MAX_VALUE?-1:index;
}
}

方案二:使用一个256大小的数组来存放每个字符出现的次数,然后再遍历字符串中的每个字符,如果该字符出现的次数为1则返回。
class Solution {
public int firstUniqChar(String s) {
int len = s.length();
if(len==0)return -1;
int[] charTable = new int[256];
for(int i=0;i<len;i++){
int index = s.charAt(i)-‘0’;
charTable[index]++;
}
for(int i=0;i<len;i++){
int index = s.charAt(i)-‘0’;
if(charTable[index]==1)return i;
}
return -1;
}
}

有效的字母异位词

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词。
如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?

class Solution {
public boolean isAnagram(String s, String t) {
int lens = s.length();
int lent = t.length();
if(lens!=lent)return false;
HashMap<Character, Integer> map = new HashMap<>();
for(int i=0;i<lens;i++){
char curr = s.charAt(i);
if(map.containsKey(curr))map.put(curr, map.get(curr)+1);
else map.put(curr, 1);
}
for(int i=0;i<lent;i++){
char curr = t.charAt(i);
if(!map.containsKey(curr)||map.get(curr)==0)return false;
map.put(curr, map.get(curr)-1);
}
Iterator it = map.values().iterator();
while(it.hasNext()){
if((int)it.next()!=0)return false;
}
return true;
}
}

验证回文字符串

给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写。
说明:本题中,我们将空字符串定义为有效的回文串。

注意小写字符比大写字符大32!
class Solution {
public boolean isPalindrome(String s) {
int len = s.length();
if(len<2)return true;
int left = 0;
int right = len-1;
while(left<right){
while(left<right&&letter(s.charAt(left))==null)left++;
while(left<right&&letter(s.charAt(right))==null)right–;
if(left<right&&letter(s.charAt(left))!=letter(s.charAt(right)))return false;
left++;
right–;
}
return true;
}
public Character letter(char c){
if(c>=‘a’&&c<=‘z’||c>=‘0’&&c<=‘9’)return c;
else if(c>=‘A’&&c<=‘Z’)return (char)(c+32);
else return null;
}
}

字符串转整数 (atoi)

实现 atoi,将字符串转为整数。
在找到第一个非空字符之前,需要移除掉字符串中的空格字符。如果第一个非空字符是正号或负号,选取该符号,并将其与后面尽可能多的连续的数字组合起来,这部分字符即为整数的值。如果第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。
字符串可以在形成整数的字符后面包括多余的字符,这些字符可以被忽略,它们对于函数没有影响。
当字符串中的第一个非空字符序列不是个有效的整数;或字符串为空;或字符串仅包含空白字符时,则不进行转换。
若函数不能执行有效的转换,返回 0。
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [?231, 231 ? 1]。如果数值超过可表示的范围,则返回 INT_MAX (231 ? 1) 或 INT_MIN (?231) 。

public class Solution {
public int myAtoi(String str) {
str = str.trim();
if (str.isEmpty()) return 0;
int sign = 1, base = 0, i = 0, n = str.length();
if (str.charAt(i) == ‘+’ || str.charAt(i) == ‘-’) {
sign = (str.charAt(i++) == ‘+’) ? 1 : -1;
}
while (i < n && str.charAt(i) >= ‘0’ && str.charAt(i) <= ‘9’) {
if (base > Integer.MAX_VALUE / 10 || (base == Integer.MAX_VALUE / 10 && str.charAt(i) - ‘0’ > 7)) {
return (sign == 1) ? Integer.MAX_VALUE : Integer.MIN_VALUE;
}
base = 10 * base + (str.charAt(i++) - ‘0’);
}
return base * sign;
}
}

实现strStr()

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回-1。如果needle是空字符串,则返回0 。

class Solution {
public int strStr(String haystack, String needle) {
int len1 = haystack.length();
int len2 = needle.length();
if(len2==0)return 0;
if(len1<len2)return -1;
int i = 0;
int j = 0;
while(i<len1&&j<len2){
if(haystack.charAt(i)needle.charAt(j)){
j++;
i++;
}else{
i = i-j+1;
j = 0;
}
}
if(j
len2)return i-j;
else return -1;
}
}

数数并说

报数序列是指一个整数序列,按照其中的整数的顺序进行报数,得到下一个数。其前五项如下:

  1. 1
  2. 11
  3. 21
  4. 1211
  5. 111221
    1 被读作 “one 1” (“一个一”) , 即 11。
    11 被读作 “two 1s” (“两个一”), 即 21。
    21 被读作 “one 2”, “one 1” (“一个二” , “一个一”) , 即 1211。

给定一个正整数 n ,输出报数序列的第 n 项。
注意:整数顺序将表示为一个字符串

class Solution {
public String countAndSay(int n) {
String countSequence=“1”;
if(n==1)return countSequence;
for(int i=2;i<=n;i++){
StringBuffer sb=new StringBuffer();
for(int j=0;j<countSequence.length()😉{
char current=countSequence.charAt(j);
int num=0;
while(j<countSequence.length()&&countSequence.charAt(j)==current){
num++;
j++;
}
sb.append(String.valueOf(num));
sb.append(current);
}
countSequence=sb.toString();
}
return countSequence;
}
}

mid-最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。

使用startsWith()方法判断一个字符串是不是另一个字符串的前缀。
class Solution {
public String longestCommonPrefix(String[] strs) {
int count=strs.length;
String prefix=“”;
if(count!=0){
prefix=strs[0];
}
for(int i=0;i<count;i++){
while(!strs[i].startsWith(prefix)){
prefix=prefix.substring(0,prefix.length()-1);
}
}
return prefix;
}
}

1 两数之和

给定一个整数数组和一个目标值,找出数组中和为目标值的两个数,返回它们的坐标。
你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。

用HashMap!!!
class Solution {
public int[] twoSum(int[] nums, int target) {
int len = nums.length;
if(len<2)return null;
HashMap<Integer, Integer> map = new HashMap<>();
for(int i=0;i<len;i++){
if(map.containsKey(target-nums[i])){
return new int[]{i, map.get(target-nums[i])};
}
map.put(nums[i], i);
}
return null;
}
}

mid-15 三数之和 双指针

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。

先对数组进行排序,然后遍历数组中小于等于0的部分,每次将当前元素设为三数中的其中一个,然后对数组剩余的部分运用两数之和的算法。
public List<List> threeSum(int[] nums) {
List<List> res = new ArrayList<List>();
if(nums == null || nums.length <= 2) return res;
Arrays.sort(nums);
for(int i = 0; i < nums.length; i++){
if(nums[i] > 0) break;
if(i > 0 && nums[i] == nums[i-1]) continue; //去重
int target = -nums[i];
int left = i+1;
int right = nums.length-1;
while(left < right){
if(nums[left] + nums[right] == target){
List sublist = new ArrayList();
sublist = Arrays.asList(nums[i],nums[left],nums[right]);
res.add(sublist);
left++;
right–;
while (nums[left] == nums[left-1] && left < right) left++;
while (nums[right] == nums[right+1] && left < right) right–;
}else if(nums[left] + nums[right] < target){
left++;
}else{
right–;
}
}
}
return res;
}
class Solution {
public List<List> threeSum(int[] nums) {
List<List> res = new ArrayList<>();
int len = nums.length;
if(len<3)return res;
Arrays.sort(nums);
int i = 0;
while(i<len&&nums[i]<=0){
int target = 0-nums[i];
int left = i+1;
int right = len-1;
while(left<right){
if(nums[left]+nums[right]==target){
res.add(Arrays.asList(nums[i], nums[left], nums[right]));
int l = nums[left];
while(left<right&&nums[left]==l)left++;
int r = nums[right];
while(left<right&&nums[right]==r)right–;
}else if(nums[left]+nums[right]>target)right–;
else left++;
}
int temp = nums[i];
while(i<len&&nums[i]==temp)i++;
}
return res;
}
}

mid-16 最接近的三数之和 双指针

三数之和最接近target,返回三数之和。假定存在一个解
public int threeSumClosest(int[] nums, int target) {
Arrays.sort(nums);
int res = nums[0]+nums[1]+nums[2];
for(int i = 0; i < nums.length-2; i++){
int left = i+1;
int right = nums.length-1;
while (left < right){
int sum = nums[i]+nums[left]+nums[right];
int dev = Math.abs(sum-target);

        if(Math.abs(res-target) > dev){
            res = sum;
        }
        if(sum < target){
            left++;
        }else{
            right--;
        }
    }
}
return res;

}

mid-18 四数之和 双指针+双循环

/*
给定一个包含 n 个整数的数组 nums 和一个目标值 target,
判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?
找出所有满足条件且不重复的四元组。

给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。

满足要求的四元组集合为:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]

使用双循环固定两个数,用双指针找另外两个数,通过比较与target 的大小(3数之和),移动指针。
??如何跳过重复值
方法一:使用set:不能存重复值
方法二:当有重复值,改变索引(例如sum3)
*/
public class Sum4 {
public List<List> fourSum(int[] nums, int target) {
List<List> resList = new ArrayList<List>();
Arrays.sort(nums);
Set<List> set = new HashSet<List>();
int l = nums.length;
for(int i = 0; i < l-3; i++) {
if(nums[i] > target && target > 0) break;
for(int j = i+1; j < l-2; j++) {
int start = j+1;
int end = l-1;
while(start < end) {
int sum = nums[i]+nums[j]+nums[start]+nums[end];
if(sum == target) {
set.add(Arrays.asList(nums[i],nums[j],nums[start],nums[end]));
start++;
end–;
}else if(sum < target) {
start++;
}else {
end–;
}
}
}
}
for(List list : set) {
resList.add(list);
}
return resList;
}
}

mid-11盛最多水的容器 双指针

public int maxArea(int[] height) {
if(height == null || height.length <= 1) return 0;
int left = 0;
int right = height.length-1;
int res = 0;

while(left < right){
    res = Math.max(res, (right-left)*Math.min(height[right],height[left]));
    if(height[left] < height[right]){
        left++;
    }else{
        right--;
    }
}
return res;

}

mid-31 下一个排列 双指针

必须 原地 修改,只允许使用额外常数空间。
思路:
从右往左遍历,找到num[i-1]<nums[i]的位置i-1,然后遍历第二次,找到比num[i-1]数字大的数,二者交换,然后对i-1之后的元素进行翻转
时间复杂度:O(N)O(N),其中 NN 为给定序列的长度。我们至多只需要扫描两次序列,以及进行一次反转操作。
空间复杂度:O(1)O(1),只需要常数的空间存放若干变量

public void nextPermutation(int[] nums) {
int left = -1;
int right = 0;
for(int i = nums.length - 1; i > 0; i–) {
if(nums[i-1] < nums[i]) {
left = i-1;
break;
}
}
if(left >= 0) { //对于321,其下一个排列是第一个123,所以第二次循环和交换不需要做
for(int i = nums.length - 1; i > left; i–) {
if(nums[i] > nums[left]){
right = i;
break;
}
}
int tmp = nums[left];
nums[left] = nums[right];
nums[right] = tmp;
}
reserve(left + 1, nums);
}
public void reserve(int begin, int[] nums){
int end = nums.length - 1;
while(begin < end){
int tmp = nums[begin];
nums[begin] = nums[end];
nums[end] = tmp;
begin ++;
end --;
}
}

88 合并两个有序数组 逆向 双指针

逆向
//非递减数组,合并后仍保持非递减
//输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
//输出:[1,2,2,3,5,6]
public void merge(int[] nums1, int m, int[] nums2, int n) {
int last = m+n; //逆向
while(n > 0){
if(m > 0 && nums1[m-1] > nums2[n-1]){
nums1[–last] = nums1[–m];
}else{
nums1[–last] = nums2[–n];
}
}
}

mid-四数相加

/*

  • 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0。

  • 遍历 A 和 B 所有元素和的组合情况,并记录在 ab_map 中,ab_map 的 key 为两数和,value 为该两数和出现的次数
    遍历 C 和 D 所有元素和的组合情况,取和的负值判断其是否在 ab_map 中,若存在则取出 ab_map 对应的 value 值,count = count + value
    */
    public class Sum4_2 {

    public int fourSumCount(int[] A, int[] B, int[] C, int[] D) {
    int count = 0;
    Map<Integer,Integer> map = new HashMap<Integer,Integer>();
    int len = A.length;
    for(int i = 0; i < len; i++) {
    for(int j = 0; j < len; j++) {
    int val = 0;
    if(map.containsKey(A[i]+B[j])) {
    val = (A[i]+B[j])+1;
    }else {
    val = 1;
    }
    map.put(A[i]+B[j], val);
    }
    }

     for(int m = 0; m < len; m++) {
     	for(int n = 0; n < len; n++) {
     		int sum = -(C[m]+D[n]);
     		int val = 0;
     		if(map.containsKey(sum)) {
     			val = sum;
     		}
     		count += val;
     	}
     }
     
     return count;
    

    }
    }

mid-矩阵置零

给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。
你能想出一个常数空间的解决方案吗?

用第一行的元素表示每一列是否存在0,第一列的元素表示每一行是否存在0,再使用额外两个变量firstRowIsZero,firstColIsZero判断第一行以及第一列本身是否存在0。
class Solution {
public void setZeroes(int[][] matrix) {
int row = matrix.length;
if(row0)return;
int col = matrix[0].length;
if(col
0)return;
boolean firstRowIsZero = false;
boolean firstColIsZero = false;
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
if(i!=0&&j!=0&&matrix[i][j]0){
matrix[i][0] = 0;
matrix[0][j] = 0;
}else if(matrix[i][j]0){
firstRowIsZero = i
0 ? true:firstRowIsZero;
firstColIsZero = j
0 ? true:firstColIsZero;
}
}
}
for(int i=1;i<row;i++){
if(matrix[i][0]==0){
for(int j=1;j<col;j++)matrix[i][j] = 0;
}
}
for(int j=1;j<col;j++){
if(matrix[0][j]==0){
for(int i=1;i<row;i++)matrix[i][j] = 0;
}
}
if(firstRowIsZero){
for(int j=0;j<col;j++)matrix[0][j] = 0;
}
if(firstColIsZero){
for(int i=0;i<row;i++)matrix[i][0] = 0;
}
}
}

mid-字谜分组

给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串
说明:
● 所有输入均为小写字母。
● 不考虑答案输出的顺序

创建一个HashMap<String, List>,将每个词中的字母重新排序,把排好序之后的词作为key存入HashMap中,对每次词都进行同样的排序操作,然后将这个词放入对应的键值对中,最后返回HashMap中value的集合。
class Solution {
public List<List> groupAnagrams(String[] strs) {
int len = strs.length;
if(len==0)return new ArrayList<List>();
Map<String, List> map = new HashMap<>();
for(String str:strs){
char[] chars = str.toCharArray();
Arrays.sort(chars);
String keyStr = String.valueOf(chars);
if(!map.containsKey(keyStr))map.put(keyStr, new ArrayList());
map.get(keyStr).add(str);
}
return new ArrayList<List>(map.values());
}
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-09-04 01:36:44  更:2022-09-04 01:40:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 21:15:15-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码