编程合集: https://www.cnblogs.com/jssj/p/12002760.html

前言:不仅仅要实现,更要提升性能,精益求精,用尽量少的时间复杂度和空间复杂度解决问题。

【程序88】
给定一个未排序的整数数组,找出其中没有出现的最小的正整数。

/**
* 给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
*/
public class Subject88 {
public static void main(String[] args) {
int[] arrInt = new int[]{-1,-9,1,2,4,6,9,8};
int number = new Subject88().firstMissingPositive(arrInt);
System.out.println(number);
} public int firstMissingPositive(int[] nums) {
int n = nums.length; // 基本情况
int contains = 0;
for (int i = 0; i < n; i++) {
if (nums[i] == 1) {
contains++;
break;
}
}
if (contains == 0)
return 1; // nums = [1]
if (n == 1)
return 2; // 用 1 替换负数,0,
// 和大于 n 的数
// 在转换以后,nums 只会包含
// 正数
for (int i = 0; i < n; i++)
if ((nums[i] <= 0) || (nums[i] > n))
nums[i] = 1; // 使用索引和数字符号作为检查器
// 例如,如果 nums[1] 是负数表示在数组中出现了数字 `1`
// 如果 nums[2] 是正数 表示数字 2 没有出现
for (int i = 0; i < n; i++) {
int a = Math.abs(nums[i]);
// 如果发现了一个数字 a - 改变第 a 个元素的符号
// 注意重复元素只需操作一次
if (a == n)
nums[0] = - Math.abs(nums[0]);
else
nums[a] = - Math.abs(nums[a]);
} // 现在第一个正数的下标
// 就是第一个缺失的数
for (int i = 1; i < n; i++) {
if (nums[i] > 0)
return i;
} if (nums[0] > 0)
return n; return n + 1;
}
}

时间复杂度为 O(n)。

运行结果:

《Java练习题》进阶练习题(五)-LMLPHP

【程序89】
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。感谢 Marcos 贡献此图。

/**
* 【程序89】
* 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
* 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。感谢 Marcos 贡献此图。
*/
public class Subject89 { public static void main(String[] args) {
int[] arrInt = new int[]{0,1,4,2,1,0,1,7,2,1,2,6};
int side = new Subject89().trap(arrInt);
System.out.println(side);
} public int trap(int[] height) {
int max = 0;
int side =0;
for (int i = 0; i < height.length ; i++) {
if(height[i] > max){
max = height[i];
side = i;
}
} int unit = 0;
//右边接收雨水量
unit = unit + trapRight(height,side);
//左边接受雨水量
unit = unit + trapLeft(height,side);
return unit;
} public int trapRight(int[] height,int side) {
int unit = 0;
int maxTmp = 0;
int sideTmp =0;
for (int i = height.length-1 ; i > side; i--) {
if(height[i] > maxTmp){
maxTmp = height[i];
sideTmp = i;
}
} //计算中间存在多少单位
unit = trapUnit(height,side,sideTmp);
if(maxTmp > 0 && sideTmp != height.length-1){
unit += trapRight(height,sideTmp);
}
return unit;
} public int trapLeft(int[] height,int side) {
int unit = 0;
int maxTmp = 0;
int sideTmp =0;
for (int i = 0 ; i < side; i++) {
if(height[i] > maxTmp){
maxTmp = height[i];
sideTmp = i;
}
}
//计算中间存在多少单位
unit = trapUnit(height, sideTmp,side);
if(maxTmp > 0 && sideTmp != 0) {
unit += trapLeft(height, sideTmp);
}
return unit;
} /**
* 计算中间可以存在多少单位雨水
* @param height
* @return
*/
public int trapUnit(int[] height,int left,int right){
int unit = 0;
if(right-left <= 1){
return unit;
} int low =0;
if(height[left] > height[right]){
low = height[right];
}else{
low = height[left];
} for (int i = left+1; i <= right-1; i++) {
unit = unit + (low - height[i]);
}
return unit;
}
}

时间复杂度为 O(n)。

运行结果:

《Java练习题》进阶练习题(五)-LMLPHP

【程序90】
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。

/**
* 给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
*/
public class Subject90 {
public static void main(String[] args) {
String num1 = "123";
String num2 = "456";
String nultiply = new Subject90().multiply(num1,num2);
System.out.println(nultiply);
}
public String multiply(String num1, String num2) {
if (num1.equals("0") || num2.equals("0")) {
return "0";
}
int[] res = new int[num1.length() + num2.length()];
for (int i = num1.length() - 1; i >= 0; i--) {
int n1 = num1.charAt(i) - '0';
for (int j = num2.length() - 1; j >= 0; j--) {
int n2 = num2.charAt(j) - '0';
int sum = (res[i + j + 1] + n1 * n2);
res[i + j + 1] = sum % 10;
res[i + j] += sum / 10;
}
} StringBuilder result = new StringBuilder();
for (int i = 0; i < res.length; i++) {
if (i == 0 && res[i] == 0) continue;
result.append(res[i]);
}
return result.toString();
}
}

时间复杂度为 O(MN)。

运行结果:

《Java练习题》进阶练习题(五)-LMLPHP

【程序91】
给定一个字符串(s) 和一个字符模式(p) ,实现一个支持'?'和'*'的通配符匹配。
'?' 可以匹配任何单个字符。
'*' 可以匹配任意字符串(包括空字符串)。
两个字符串完全匹配才算匹配成功。

/**
* 给定一个字符串(s) 和一个字符模式(p) ,实现一个支持'?'和'*'的通配符匹配。
* '?' 可以匹配任何单个字符。
* '*' 可以匹配任意字符串(包括空字符串)。
* 两个字符串完全匹配才算匹配成功。
*/
public class Subject91 {
public static void main(String[] args) {
String str1 = "abbabaaabababbaababbabbbbbabbbabb";
String str2 = "**aa*abb***";
System.out.println(new Subject91().isMatch(str1,str2));
} boolean isMatch(String str, String pattern) { int s = 0, p = 0, match = 0, starIdx = -1;
//遍历整个字符串
while (s < str.length()){
// 一对一匹配,两指针同时后移。
if (p < pattern.length() && (pattern.charAt(p) == '?' || str.charAt(s) == pattern.charAt(p))){
s++;
p++;
}
// 碰到 *,假设它匹配空串,并且用 startIdx 记录 * 的位置,记录当前字符串的位置,p 后移
else if (p < pattern.length() && pattern.charAt(p) == '*'){
starIdx = p;
match = s;
p++;
}
// 当前字符不匹配,并且也没有 *,回退
// p 回到 * 的下一个位置
// match 更新到下一个位置
// s 回到更新后的 match
// 这步代表用 * 匹配了一个字符
else if (starIdx != -1){
p = starIdx + 1;
match++;
s = match;
}
//字符不匹配,也没有 *,返回 false
else return false;
} //将末尾多余的 * 直接匹配空串 例如 text = ab, pattern = a*******
while (p < pattern.length() && pattern.charAt(p) == '*')
p++; return p == pattern.length();
}
}

时间复杂度为 O(TP)。

运行结果:

《Java练习题》进阶练习题(五)-LMLPHP

【程序92】
给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。

/**
* 给定一个非负整数数组,你最初位于数组的第一个位置。
* 数组中的每个元素代表你在该位置可以跳跃的最大长度。
* 你的目标是使用最少的跳跃次数到达数组的最后一个位置。
*/
public class Subject92 { public static void main(String[] args) {
int[] arrInt = new int[]{2,3,1,1,4,2,1};
System.out.println(new Subject92().jump(arrInt));
} public int jump(int[] nums) {
//小于等于1的都不需要跳
int lengths = nums.length;
if(lengths <= 1){
return 0;
}
int reach = 0; //当前能走的最远距离
int nextreach = nums[0];
int step = 0; //需要步数
for(int i = 0;i<lengths;i++){
//贪心算法核心:这一步是不是可以比上一步得到更多步数,可以则取最新的路线。
nextreach = Math.max(i+nums[i],nextreach);
if(nextreach >= lengths-1) return (step+1);
if(i == reach){
step++;
reach = nextreach;
}
}
return step;
}
}

时间复杂度为 O(n)。

运行结果:

《Java练习题》进阶练习题(五)-LMLPHP

【程序93】
给定一个没有重复数字的序列,返回其所有可能的全排列。

import java.util.ArrayList;
import java.util.List; /**
* 给定一个没有重复数字的序列,返回其所有可能的全排列。
*/
public class Subject93 {
public static void main(String[] args) {
int[] arrInt = new int[]{1,2,3};
List<List<Integer>> integerList1 = new Subject93().permute(arrInt);
System.out.println(integerList1);
} List<List<Integer>> integerList = new ArrayList<>();
List<Integer> integerListTmp = new ArrayList<>(); int index = -1; /**
* 就一步步实现呗
* @param nums
* @return
*/
public List<List<Integer>> permute(int[] nums) { List<Integer> numList = new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
numList.add(nums[i]);
integerListTmp.add(nums[i]);
}
index = nums.length;
permute(numList);
return integerList;
} public void permute(List<Integer> numList) {
int sizes = numList.size();
if (sizes <= 0) {
return ;
}
for (int i = 0; i < sizes; i++) {
integerListTmp.set(index- sizes,numList.get(i));
if(sizes <= 1){
List<Integer> numListTmp0 = new ArrayList<>();
numListTmp0.addAll(integerListTmp);
integerList.add(numListTmp0);
return;
}
List<Integer> numListTmp = new ArrayList<>();
numListTmp.addAll(numList);
numListTmp.remove(i);
permute(numListTmp);
}
}
}

时间复杂度为 《Java练习题》进阶练习题(五)-LMLPHP

运行结果:

《Java练习题》进阶练习题(五)-LMLPHP

【程序94】
给定一个可包含重复数字的序列,返回所有不重复的全排列。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map; /**
* 给定一个可包含重复数字的序列,返回所有不重复的全排列。
*/
public class Subject94 {
public static void main(String[] args) {
int[] arrInt = new int[]{3,1,3,3};
List<List<Integer>> integerList1 = new Subject94().permuteUnique(arrInt);
System.out.println(integerList1);
} List<List<Integer>> integerList = new ArrayList<>();
List<Integer> integerListTmp = new ArrayList<>(); int index = -1; /**
* 使用排序后,
* 剪枝的方式实现。
* @param nums
* @return
*/
public List<List<Integer>> permuteUnique(int[] nums) {
List<Integer> numList = new ArrayList<>();
//排序
Arrays.sort(nums); for (int i = 0; i < nums.length; i++) {
numList.add(nums[i]);
integerListTmp.add(nums[i]);
}
index = nums.length;
permuteUnique(numList);
return integerList;
} public void permuteUnique(List<Integer> numList) {
int sizes = numList.size();
if (sizes <= 0) {
return ;
}
Map<Integer,Integer> map = new HashMap<>();
for (int i = 0; i < sizes; i++) {
Integer integer = map.get(index- sizes);
if(integer != null){
if(integer == numList.get(i)){ //多余的分支都剪掉
continue;
}else{
map.put(index- sizes,numList.get(i));
}
}else{
map.put(index- sizes,numList.get(i));
} if(integerListTmp.get(index- sizes) != numList.get(i)){
integerListTmp.set(index- sizes,numList.get(i));
}
if(sizes <= 1){
List<Integer> numListTmp0 = new ArrayList<>();
numListTmp0.addAll(integerListTmp);
integerList.add(numListTmp0);
return;
}
List<Integer> numListTmp = new ArrayList<>();
numListTmp.addAll(numList);
numListTmp.remove(i);
permuteUnique(numListTmp);
}
}
}

时间复杂度为 《Java练习题》进阶练习题(五)-LMLPHP

运行结果:

《Java练习题》进阶练习题(五)-LMLPHP

【程序95】
给定一个 n×n 的二维矩阵表示一个图像。
将图像顺时针旋转 90 度。
说明:
你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。

/**
* 给定一个 n×n 的二维矩阵表示一个图像。
* 将图像顺时针旋转 90 度。
* 说明:
* 你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
*/
public class Subject95 {
public static void main(String[] args) {
int[][] arrInt = new int[][]{{1,2,3},{4,5,6},{7,8,9}};
new Subject95().rotate(arrInt);
System.out.println(arrInt);
} public void rotate(int[][] matrix) {
int n = matrix.length;
for (int i = 0; i < (n + 1) / 2; i ++) {
for (int j = 0; j < n / 2; j++) {
int temp = matrix[n - 1 - j][i];
matrix[n - 1 - j][i] = matrix[n - 1 - i][n - j - 1];
matrix[n - 1 - i][n - j - 1] = matrix[j][n - 1 -i];
matrix[j][n - 1 - i] = matrix[i][j];
matrix[i][j] = temp;
}
}
}
}

时间复杂度为 O(n^2)。

运行结果:

《Java练习题》进阶练习题(五)-LMLPHP

【程序96】
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
示例:
输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
输出:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
说明:
所有输入均为小写字母。
不考虑答案输出的顺序。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map; /**
* 给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
* 示例:
* 输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
* 输出:
* [
* ["ate","eat","tea"],
* ["nat","tan"],
* ["bat"]
* ]
* 说明:
* 所有输入均为小写字母。
* 不考虑答案输出的顺序。
*/
public class Subject96 {
public static void main(String[] args) {
String[] strArr = new String[]{"eat", "tea", "tan", "ate", "nat", "bat"};
List<List<String>> listList = new Subject96().groupAnagrams(strArr);
System.out.println(listList);
} List<List<String>> listList = new ArrayList<>();
Map<String,List<String>> map = new HashMap<>();
public List<List<String>> groupAnagrams(String[] strs) {
for (int i = 0; i < strs.length; i++) {
char[] ch = strs[i].toCharArray();
String str = dealChar(ch);
if(map.get(str) == null){
List<String> list = new ArrayList<>();
list.add(strs[i]);
map.put(str,list);
}else{
List<String> list = map.get(str);
list.add(strs[i]);
}
} Iterator<Map.Entry<String, List<String>>> it=map.entrySet().iterator();
while(it.hasNext()){
Map.Entry<String, List<String>> entry=it.next();
listList.add(entry.getValue());
} return listList;
} public String dealChar(char[] ch) {
Arrays.sort(ch);
return new String(ch,0,ch.length);
}
}

时间复杂度为 O(nk)。

运行结果:

《Java练习题》进阶练习题(五)-LMLPHP

【程序97】
实现 pow(x, n) ,即计算 x 的 n 次幂函数。
-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是 [?2^31, 2^31 ? 1] 。

import java.util.HashMap;
import java.util.Map; /**
* 实现 pow(x, n) ,即计算 x 的 n 次幂函数。
* -100.0 < x < 100.0
* n 是 32 位有符号整数,其数值范围是 [?2^31, 2^31 ? 1] 。
*/
public class Subject97 { public static void main(String[] args) {
double dou = new Subject97().myPow(1.13183,-2147483648);
System.out.println(dou);
} Map<Integer,Double> map = new HashMap<>(); public double myPow(double x, int n) {
double dou = 1.0; if(n > 0){
if(n < 10){
for (int i =0 ;i < n; i++){
dou = dou*x ;
}
}else{
map.put(1,x);
map.put(2,x*x);
map.put(4,x*x*x*x);
map.put(8,x*x*x*x*x*x*x*x); int index = 8;
while(index <= n/2 && index < 1073741824){
int tmp = index;
index = index*2;
map.put(index,map.get(tmp)* map.get(tmp));
} dou = map.get(index);
int surplus = n - index;
while(surplus > 0){
index = index/2;
if(surplus >= index){
dou = dou*map.get(index);
}else{
continue;
}
surplus = surplus - index;
if(index == 1){
break;
}
}
} }else if(n == 0){
return 1;
}else{
if(n > -10){
for (int i =0 ;i < -n; i++){
dou = dou*(1.0/x) ;
}
}else{
map.put(-1,1.0/x);
map.put(-2,(1.0/x)*(1.0/x));
map.put(-4,(1.0/x)*(1.0/x)*(1.0/x)*(1.0/x));
map.put(-8,(1.0/x)*(1.0/x)*(1.0/x)*(1.0/x)*(1.0/x)*(1.0/x)*(1.0/x)*(1.0/x)); int index = -8;
while(index >= n/2 ){
int tmp = index;
index = index*2;
map.put(index,map.get(tmp)* map.get(tmp));
} dou = map.get(index);
int surplus = n - index;
while(surplus < 0){
index = index/2;
if(surplus <= index){
dou = dou*map.get(index);
}else{
continue;
}
surplus = surplus - index;
if(index == -1){
break;
}
}
}
}
return dou;
}
}

时间复杂度为 O(n)。

运行结果:

《Java练习题》进阶练习题(五)-LMLPHP

以上题目均来自:https://leetcode-cn.com/ ,如果你热爱编码,热爱算法,该网站一定适合你。

05-15 17:59