前言:不仅仅要实现,更要提升性能,精益求精,用尽量少的时间复杂度和空间复杂度解决问题。
【程序88】
给定一个未排序的整数数组,找出其中没有出现的最小的正整数。
/*** 给定一个未排序的整数数组,找出其中没有出现的最小的正整数。*/
public classSubject88 {public static voidmain(String[] args) {int[] arrInt = new int[]{-1,-9,1,2,4,6,9,8};int number = newSubject88().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]);elsenums[a]= -Math.abs(nums[a]);
}//现在第一个正数的下标//就是第一个缺失的数
for (int i = 1; i < n; i++) {if (nums[i] > 0)returni;
}if (nums[0] > 0)returnn;return n + 1;
}
}
时间复杂度为 O(n)。
运行结果:
【程序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 classSubject89 {public static voidmain(String[] args) {int[] arrInt = new int[]{0,1,4,2,1,0,1,7,2,1,2,6};int side = newSubject89().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);returnunit;
}public int trapRight(int[] height,intside) {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);
}returnunit;
}public int trapLeft(int[] height,intside) {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);
}returnunit;
}/*** 计算中间可以存在多少单位雨水
*@paramheight
*@return
*/
public int trapUnit(int[] height,int left,intright){int unit = 0;if(right-left <= 1){returnunit;
}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]);
}returnunit;
}
}
时间复杂度为 O(n)。
运行结果:
【程序90】
给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。
/*** 给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。*/
public classSubject90 {public static voidmain(String[] args) {
String num1= "123";
String num2= "456";String nultiply= newSubject90().multiply(num1,num2);
System.out.println(nultiply);
}publicString 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= newStringBuilder();for (int i = 0; i < res.length; i++) {if (i == 0 && res[i] == 0) continue;
result.append(res[i]);
}returnresult.toString();
}
}
时间复杂度为 O(MN)。
运行结果:
【程序91】
给定一个字符串(s) 和一个字符模式(p) ,实现一个支持'?'和'*'的通配符匹配。
'?' 可以匹配任何单个字符。
'*' 可以匹配任意字符串(包括空字符串)。
两个字符串完全匹配才算匹配成功。
/*** 给定一个字符串(s) 和一个字符模式(p) ,实现一个支持'?'和'*'的通配符匹配。
* '?' 可以匹配任何单个字符。
* '*' 可以匹配任意字符串(包括空字符串)。
* 两个字符串完全匹配才算匹配成功。*/
public classSubject91 {public static voidmain(String[] args) {
String str1= "abbabaaabababbaababbabbbbbabbbabb";
String str2= "**aa*abb***";
System.out.println(newSubject91().isMatch(str1,str2));
}booleanisMatch(String str, String pattern) {int s = 0, p = 0, match = 0, starIdx = -1;//遍历整个字符串
while (s
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)。
运行结果:
【程序92】
给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
/*** 给定一个非负整数数组,你最初位于数组的第一个位置。
* 数组中的每个元素代表你在该位置可以跳跃的最大长度。
* 你的目标是使用最少的跳跃次数到达数组的最后一个位置。*/
public classSubject92 {public static voidmain(String[] args) {int[] arrInt = new int[]{2,3,1,1,4,2,1};
System.out.println(newSubject92().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
nextreach = Math.max(i+nums[i],nextreach);if(nextreach >= lengths-1) return (step+1);if(i ==reach){
step++;
reach=nextreach;
}
}returnstep;
}
}
时间复杂度为 O(n)。
运行结果:
【程序93】
给定一个没有重复数字的序列,返回其所有可能的全排列。
importjava.util.ArrayList;importjava.util.List;/*** 给定一个没有重复数字的序列,返回其所有可能的全排列。*/
public classSubject93 {public static voidmain(String[] args) {int[] arrInt = new int[]{1,2,3};
List> integerList1 = newSubject93().permute(arrInt);
System.out.println(integerList1);
}
List> integerList = new ArrayList<>();
List integerListTmp = new ArrayList<>();int index = -1;/*** 就一步步实现呗
*@paramnums
*@return
*/
public List> permute(int[] nums) {
List numList = new ArrayList<>();for (int i = 0; i < nums.length; i++) {
numList.add(nums[i]);
integerListTmp.add(nums[i]);
}
index=nums.length;
permute(numList);returnintegerList;
}public void permute(ListnumList) {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 numListTmp0 = new ArrayList<>();
numListTmp0.addAll(integerListTmp);
integerList.add(numListTmp0);return;
}
List numListTmp = new ArrayList<>();
numListTmp.addAll(numList);
numListTmp.remove(i);
permute(numListTmp);
}
}
}
时间复杂度为
。
运行结果:
【程序94】
给定一个可包含重复数字的序列,返回所有不重复的全排列。
importjava.util.ArrayList;importjava.util.Arrays;importjava.util.HashMap;importjava.util.List;importjava.util.Map;/*** 给定一个可包含重复数字的序列,返回所有不重复的全排列。*/
public classSubject94 {public static voidmain(String[] args) {int[] arrInt = new int[]{3,1,3,3};
List> integerList1 = newSubject94().permuteUnique(arrInt);
System.out.println(integerList1);
}
List> integerList = new ArrayList<>();
List integerListTmp = new ArrayList<>();int index = -1;/*** 使用排序后,
* 剪枝的方式实现。
*@paramnums
*@return
*/
public List> permuteUnique(int[] nums) {
List 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);returnintegerList;
}public void permuteUnique(ListnumList) {int sizes =numList.size();if (sizes <= 0) {return;
}
Map 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 numListTmp0 = new ArrayList<>();
numListTmp0.addAll(integerListTmp);
integerList.add(numListTmp0);return;
}
List numListTmp = new ArrayList<>();
numListTmp.addAll(numList);
numListTmp.remove(i);
permuteUnique(numListTmp);
}
}
}
时间复杂度为
。
运行结果:
【程序95】
给定一个 n×n 的二维矩阵表示一个图像。
将图像顺时针旋转 90 度。
说明:
你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
/*** 给定一个 n×n 的二维矩阵表示一个图像。
* 将图像顺时针旋转 90 度。
* 说明:
* 你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。*/
public classSubject95 {public static voidmain(String[] args) {int[][] arrInt = new int[][]{{1,2,3},{4,5,6},{7,8,9}};newSubject95().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)。
运行结果:
【程序96】
给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
示例:
输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
输出:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
说明:
所有输入均为小写字母。
不考虑答案输出的顺序。
importjava.util.ArrayList;importjava.util.Arrays;importjava.util.HashMap;importjava.util.Iterator;importjava.util.List;importjava.util.Map;/*** 给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。
* 示例:
* 输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
* 输出:
* [
* ["ate","eat","tea"],
* ["nat","tan"],
* ["bat"]
* ]
* 说明:
* 所有输入均为小写字母。
* 不考虑答案输出的顺序。*/
public classSubject96 {public static voidmain(String[] args) {
String[] strArr= new String[]{"eat", "tea", "tan", "ate", "nat", "bat"};
List> listList = newSubject96().groupAnagrams(strArr);
System.out.println(listList);
}
List> listList = new ArrayList<>();
Map> map = new HashMap<>();public List>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 list = new ArrayList<>();
list.add(strs[i]);
map.put(str,list);
}else{
List list =map.get(str);
list.add(strs[i]);
}
}
Iterator>> it=map.entrySet().iterator();while(it.hasNext()){
Map.Entry> entry=it.next();
listList.add(entry.getValue());
}returnlistList;
}public String dealChar(char[] ch) {
Arrays.sort(ch);return new String(ch,0,ch.length);
}
}
时间复杂度为 O(nk)。
运行结果:
【程序97】
实现 pow(x, n) ,即计算 x 的 n 次幂函数。
-100.0 < x < 100.0
n 是 32 位有符号整数,其数值范围是 [?2^31, 2^31 ? 1] 。
importjava.util.HashMap;importjava.util.Map;/*** 实现 pow(x, n) ,即计算 x 的 n 次幂函数。
* -100.0 < x < 100.0
* n 是 32 位有符号整数,其数值范围是 [?2^31, 2^31 ? 1] 。*/
public classSubject97 {public static voidmain(String[] args) {double dou = new Subject97().myPow(1.13183,-2147483648);
System.out.println(dou);
}
Map map = new HashMap<>();public double myPow(double x, intn) {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;
}
}
}
}returndou;
}
}
时间复杂度为 O(n)。
运行结果:
以上题目均来自:https://leetcode-cn.com/ ,如果你热爱编码,热爱算法,该网站一定适合你。