编程合集: https://www.cnblogs.com/jssj/p/12002760.html
前言:不仅仅要实现,更要提升性能,精益求精,用尽量少的时间复杂度和空间复杂度解决问题。
【程序48】
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标
import java.util.HashMap;
import java.util.Map;
/**
* 【程序48】
* 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标
*/
public class Subject48 {
public static void main(String[] args) {
int[] nums = new int[]{1,4,5,6,7,9,76,43,22,11};
int target = 11;
int[] result = twoSum(nums,target);
for (int i = 0; i < result.length; i++) {
System.out.println(result[i]);
}
}
/**
* 获取满足条件的数组下标
* @param nums
* @param target
*/
private static int[] twoSum(int[] nums, int target) {
int[] temp = new int[2];
Map<Integer,Integer> map = new HashMap<>();
//遍历查找
for(int i = 0; i < nums.length; i++){
int a = nums[i];
//判断键值是否存在
if(map.containsKey(target - a)){
temp[0] = map.get(target - a);
temp[1] = i;
return temp;
}else {//如果找不到则存进去
map.put(nums[i], i);
}
}
return null;
}
}
时间复杂度为 O(n)。
运行结果:
【程序49】
给出两个非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0开头。
public class ListNode {
int val;
ListNode next;
ListNode(){
}
ListNode(int x) { val = x; }
}
/**
* 【程序49】
* 给出两个非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照逆序的方式存储的,并且它们的每个节点只能存储一位数字。
* 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
* 您可以假设除了数字 0 之外,这两个数都不会以 0开头。
*
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
}
*/
public class Subject49 {
public static void main(String[] args) {
ListNode l1 = new ListNode(2);
ListNode l12 = new ListNode(4);
ListNode l13 = new ListNode(3);
l1.next = l12;
l12.next = l13;
ListNode l2 = new ListNode(5);
ListNode l21 = new ListNode(6);
ListNode l22 = new ListNode(4);
l2.next = l21;
l21.next = l22;
ListNode listNode = addTwoNumbers(l1,l2);
StringBuilder stringBuilder = null;
while(listNode !=null){ //指向位置是否为空
if(stringBuilder == null){
stringBuilder = new StringBuilder();
stringBuilder.append(listNode.val);
}else{
stringBuilder.append(" -> "+ listNode.val);
}
listNode = listNode.next; // 指向下一个节点
}
System.out.println(stringBuilder.toString());
}
/**
* 链表输出和
* @param l1
* @param l2
* @return
*/
public static ListNode addTwoNumbers(ListNode l1, ListNode l2){
int carry = 0; //进位
ListNode newListNode = new ListNode(0);
ListNode tmpListNode ;
tmpListNode = newListNode;
while(true){
ListNode listNode = new ListNode(0);
int tmp = l1.val + l2.val + carry;
if(tmp < 10){
listNode.val = tmp;
carry = 0;
}else{
listNode.val = tmp%10;
carry = 1;
}
tmpListNode.next = listNode;
tmpListNode = listNode;
if(l1.next ==null && l2.next == null &&carry == 0){
break;
}
if(l1.next != null){
l1 = l1.next;
}else{
l1 = new ListNode(0);
}
if( l2.next != null){
l2 = l2.next;
}else{
l2 = new ListNode(0);
}
}
return newListNode.next;
}
}
时间复杂度:O(\max(m, n))
运行结果:
【程序50】
给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。
import java.util.ArrayList;
import java.util.List;
/**
* 给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。
*/
public class Subject50 {
public static void main(String[] args) {
String Str = "aabcdfffwwesdwhjkl";
int count = lengthOfLongestSubstring(Str);
System.out.println(count);
}
/**
* 获取字符最大长度
* @param s
* @return
*/
public static int lengthOfLongestSubstring(String s) {
char[] arr = s.toCharArray();
List<Character> list = new ArrayList<>();
int maxCount = 0;
int count;
for (int i = 0; i < arr.length; i++) {
if(list.contains(arr[i])){
count = list.size();
if(count> maxCount){
maxCount = count;
}
for (int j = 0; j < list.size(); j++) {
if(list.get(j) != arr[i]){
list.remove(j);
j--;
}else{
list.remove(j);
break;
}
}
list.add(arr[i]);
}else{
list.add(arr[i]);
}
}
if(list.size() > maxCount){
return list.size();
}else{
return maxCount;
}
}
}
时间复杂度:O(n)
运行结果:
【程序51】
给定两个大小为 m 和 n 的有序数组nums1 和nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为O(log(m + n))。
你可以假设nums1和nums2不会同时为空
/**
* 给定两个大小为 m 和 n 的有序数组nums1 和nums2。
* 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为O(log(m + n))。
* 你可以假设nums1和nums2不会同时为空
*/
public class Subject51 {
public static void main(String[] args) {
int[] nums1 = new int[]{1,2,3};
int[] nums2 = new int[]{1,2};
double arr = findMedianSortedArrays(nums1,nums2);
System.out.println(arr);
}
public static int PartSort(int arr[], int low, int high) {
int data = arr[low];
/**一次遍历的方法:插空法 定义一个data将arr[low]存起来,并把这个位置挖空*/
while (low < high) {
while (low < high && arr[high] >= data) {
high--;
}
arr[low] = arr[high];
/**从high,也就是后面往前遍历 找到比键值小的数据 插入到前面留下的空中 high位再次留下空来*/
while (low < high && arr[low] <= data) {
low++;
}
arr[high] = arr[low];
}
arr[low] = data;
/**循环退出后 low和high重合 将将键值赋给第low,并将low返回*/
return low;
}
/**
* 快速排序法
* @param arr
* @param low
* @param high
*/
public static void quickSort(int arr[], int low, int high) {
if(low<high) {
//防止发生栈溢出异常
int index = PartSort(arr, low, high);
quickSort(arr, low, index - 1);
quickSort(arr, index + 1, high);
}
}
/**
* 寻找中位数
* @param nums1
* @param nums2
* @return
*/
public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
int a = nums1.length;
int b = nums2.length;
int[] arr = new int[a+b];
double result = 0.0;
if(a >= 2 && b >=2 ){
if(nums1[0] <= nums1[1] && nums2[0] <= nums2[1] ){
if(nums1[0] >= nums2[0]){
for (int i = 0; i < b; i++) {
arr[i] = nums2[i];
}
for (int i = 0; i < a; i++) {
arr[i+b] = nums1[i];
}
}else{
for (int i = 0; i < a; i++) {
arr[i] = nums1[i];
}
for (int i = 0; i < b; i++) {
arr[i+a] = nums2[i];
}
}
}else if(nums1[0] >= nums1[1] && nums2[0] >= nums2[1]){
if(nums1[a-1] <= nums2[b-1]){
for (int i = 0; i < a; i++) {
arr[i] = nums1[a-i-1];
}
for (int i = 0; i < b; i++) {
arr[i+a] = nums2[b-i-1];
}
}else{
for (int i = 0; i < b; i++) {
arr[i] = nums1[b-i-1];
}
for (int i = 0; i < a; i++) {
arr[i+b] = nums2[a-i-1];
}
}
}else if(nums1[0] <= nums1[1] && nums2[0] >= nums2[1]){
if(nums1[0] <= nums2[b-1]){
for (int i = 0; i < a; i++) {
arr[i] = nums1[i];
}
for (int i = 0; i < b; i++) {
arr[i+a] = nums2[b-i-1];
}
}else{
for (int i = 0; i < b; i++) {
arr[i] = nums2[i];
}
for (int i = 0; i < a; i++) {
arr[i+b] = nums1[a-1-i];
}
}
}else if(nums1[0] >= nums1[1] && nums2[0] <= nums2[1]){
if(nums1[a-1] <= nums2[0]){
for (int i = 0; i < a; i++) {
arr[i] = nums1[a-1-i];
}
for (int i = 0; i < b; i++) {
arr[i+a] = nums2[i];
}
}else{
for (int i = 0; i < b; i++) {
arr[i] = nums2[i];
}
for (int i = 0; i < a; i++) {
arr[i+b] = nums1[a-1-i];
}
}
}
}else{
for (int i = 0; i < a; i++) {
arr[i] = nums1[i];
}
for (int i = 0; i < b; i++) {
arr[i+a] = nums2[i];
}
}
int right = arr.length-1;
int left = 0;
quickSort(arr,left,right);
int tmp = arr.length;
if(tmp % 2 == 0){
result = (arr[tmp/2] + arr[tmp/2 - 1]) / 2.0;
}else{
result = arr[tmp/2];
}
return result;
}
}
时间复杂度:O(log(min(m,n)))
运行结果:
【程序52】
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
/**
* 【程序52】
* 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
*/
public class Subject52 {
public static void main(String[] args) {
String str = "sdffttrrgfddfh";
String result= longestPalindrome(str);
System.out.println(result);
result = longestPalindrome1(str);
System.out.println(result);
}
/**
* Manacher算法
* @param str
* @return
*/
private static String longestPalindrome1(String str) {
char[] cStr = str.toCharArray();
//插入特殊符号
StringBuffer sBuffer = new StringBuffer();
sBuffer.append("#");
for (int i = 0; i < cStr.length; i++) {
sBuffer.append(cStr[i]);
sBuffer.append("#");
}
int id =0; //回文的中心。
int max = 0; //回文最大长度。
//辅助数组
int[] p= new int[sBuffer.length()];
for (int i = 1; i < sBuffer.length(); i++) {
if (i<max) {
p[i] = Math.min(p[2*id-i], max-i);
}else {
p[i]= 1;
}
//判断中心两边是否回文,是则++;
while (i-p[i]>=0&&i+p[i]<sBuffer.length()&&sBuffer.charAt(i-p[i])==sBuffer.charAt(i+p[i])) {
p[i]++;
}
if (i+p[i]>max) {
max = i+p[i];
id = i;
}
}
int maxl = 0 ;
int maxid =0 ;
for(int i =0 ;i<p.length;i++){
if(maxl<p[i]){
maxl=p[i];
maxid = i;
}
}
//半径包括id本身。id到第一个元素,id-r+1
int r = maxl-1;
int start = maxid-r+1;
int end = maxid+maxl-1;
StringBuffer out = new StringBuffer();
for (int i = start; i < end; i++) {
if (sBuffer.charAt(i)!='#') {
out.append(sBuffer.charAt(i));
}
}
return out.toString();
}
/**
* 获取最长回文数
* @param s
* @return
*/
public static String longestPalindrome(String s) {
String result = "";
char[] arr = s.toCharArray();
for(int i = 0 ; i < arr.length; i++){
for (int j = 0; j <= i; j++) {
//判断是否回文。
result = palindromeStr(s,arr,i,j);
if(!"".equals( result) ){
return result;
}
}
}
return result;
}
/**
* 判断字符串是否是回文字符串
* @param s
* @param arr
* @param i
* @param j
* @return
*/
private static String palindromeStr(String s,char[] arr, int i, int j) {
String result = "";
int start = j;
int end = arr.length-(i-j)-1;
while(start <= end){
if(arr[start] == arr[end]){
if(start+1 >= end){
result = s.substring(j,arr.length-(i-j));
return result;
}
start++;
end--;
}else{
break;
}
}
return result;
}
}
时间复杂度:O(n)
运行结果:
【程序53】
将一个给定字符串根据给定的行数,以从上往下、从左到右进行 |\| 字形排列
import java.util.ArrayList;
import java.util.List;
/**
* 【程序53】
* 将一个给定字符串根据给定的行数,以从上往下、从左到右进行 字形排列
*
* 输入: s = "LEETCODEISHIRING", numRows =4
* 输出:"LDREOEIIECIHNTSG"
* 解释:
* L D R
* E O E I I
* E C I H N
* T S G
*/
public class Subject53 {
public static void main(String[] args) {
String s = "LEETCODEISHIRING";
int numRows = 4;
String str = convert(s,numRows);
System.out.println(str);
}
/**
*
* @param s
* @param numRows
* @return
*/
public static String convert(String s,int numRows){
if(numRows <= 1){
return s;
}
char[] arr = s.toCharArray();
//创建numRows个字符串
List<StringBuilder> list = new ArrayList<>();
for (int i = 0; i < numRows; i++) {
StringBuilder stringBuffer = new StringBuilder();
list.add(stringBuffer);
}
int flag = 0; // 0表示顺序,1表示逆序。
int size = 1; //在第几行
for (int i = 0; i < arr.length; i++) {
if(size == numRows){
flag = 1;
}
if(size == 1){
flag = 0;
}
list.get(size-1).append(arr[i]);
if(flag == 0){
size++;
}
if(flag == 1){
size--;
}
}
StringBuilder newStringBuffer = new StringBuilder();
for (int i = 0; i < numRows; i++) {
newStringBuffer.append(list.get(i));
}
return newStringBuffer.toString();
}
}
时间复杂度:O(n)
运行结果:
【程序54】
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
/**
* 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
*/
public class Subject54 {
public static void main(String[] args) {
int x= 2147483641;
int result = reverse(x);
System.out.println(result);
result = reverse2(x);
System.out.println(result);
}
/**
* 反转
* @param x
* @return
*/
public static int reverse(int x){
String str = x+"";
char[] arr = str.toCharArray();
StringBuilder stringBuilder = new StringBuilder();
if(arr[0] == '-'){
stringBuilder.append('-');
for (int i = arr.length-1; i >= 1; i--) {
stringBuilder.append(arr[i]);
}
}else{
for (int i = arr.length-1; i >= 0; i--) {
stringBuilder.append(arr[i]);
}
}
int result = 0;
try {
result = Integer.parseInt(stringBuilder.toString());
}catch (Exception e){
result = 0;
}
return result;
}
/**
* 反转2
* @param x
* @return
*/
public static int reverse2(int x){
int rev = 0;
while (x != 0) {
int pop = x % 10;
x /= 10;
if (rev > Integer.MAX_VALUE/10 || (rev == Integer.MAX_VALUE / 10 && pop > 7)) return 0;
if (rev < Integer.MIN_VALUE/10 || (rev == Integer.MIN_VALUE / 10 && pop < -8)) return 0;
rev = rev * 10 + pop;
}
return rev;
}
}
时间复杂度:O(\log(x))
运行结果:
【程序55】
请你来实现一个 atoi 函数,使其能将字符串转换成整数。
/**
* 【程序55】
* 请你来实现一个 atoi 函数,使其能将字符串转换成整数。
*/
public class Subject55 {
public static void main(String[] args) {
String str = " -2147483649ww";
int i= myAtoi(str);
System.out.println(i);
}
public static int myAtoi(String str) {
int radix = 10;
if (str == null) {
return 0;
}else{
str = str.trim();
}
int result = 0;
boolean negative = false;
int i = 0, len = str.length();
int limit = -Integer.MAX_VALUE;
int multmin;
int digit;
if (len > 0) {
char firstChar = str.charAt(0);
if (firstChar < '0') { // Possible leading "+" or "-"
if (firstChar == '-') {
negative = true;
limit = Integer.MIN_VALUE;
} else if (firstChar != '+')
return 0;
if (len == 1) // Cannot have lone "+" or "-"
return 0;
i++;
}
multmin = limit / radix;
while (i < len) {
// Accumulating negatively avoids surprises near MAX_VALUE
digit = Character.digit(str.charAt(i++),radix);
if (digit < 0) {
break;
}
if (result < multmin) {
result = limit;
break;
}
result *= radix;
if (result < limit + digit) {
result = limit;
break;
}
result -= digit;
}
} else {
return 0;
}
return negative ? result : -result;
}
}
时间复杂度:O(n)
运行结果:
【程序56】
判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
考虑负数。
/**
* 【程序56】
* 判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。
*/
public class Subject56 {
public static void main(String[] args) {
int x = 1;
boolean flag = isPalindrome(x);
System.out.println(flag);
}
/**
* 判断x是否是回文数
* @param x
* @return
*/
public static boolean isPalindrome(int x) {
if(x < 0){
return false;
}
if(x < 10){
return true;
}
int newi = 0;
int num = x;
while(true){
if(newi>0){
newi = newi*10;
}
int i = num%10 ;
newi = newi+i;
num = num/10;
if(num <= 9){
newi = newi*10+num;
break;
}
}
if(newi == x){
return true;
}else{
return false;
}
}
}
时间复杂度:O(\log_{10}(n))
运行结果:
【程序57】
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。
'.' 匹配任意单个字符
'*' 匹配零个或多个前面的那一个元素
import java.util.HashMap;
import java.util.Map;
/**
* 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 '.' 和 '*' 的正则表达式匹配。
* '.' 匹配任意单个字符
* '*' 匹配零个或多个前面的那一个元素
*/
public class Subject57 {
public static void main(String[] args) {
Map<String ,String> map = new HashMap<>();
map.put("dddc","d*dddc"); //true;
for (Map.Entry<String,String> entry :map.entrySet()){
System.out.println(entry.getKey()+" : "+entry.getValue());
System.out.println(isMatch(entry.getKey(),entry.getValue()));
}
}
/**
* 实现匹配规则
* @param s
* @param p
* @return
*/
public static boolean isMatch(String s, String p) {
if (p.isEmpty()) return s.isEmpty();
boolean first_match = (!s.isEmpty() &&
(p.charAt(0) == s.charAt(0) || p.charAt(0) == '.'));
if (p.length() >= 2 && p.charAt(1) == '*'){
return (isMatch(s, p.substring(2)) ||
(first_match && isMatch(s.substring(1), p)));
} else {
return first_match && isMatch(s.substring(1), p.substring(1));
}
}
}
时间复杂度:O(TP)
运行结果:
以上题目均来自:https://leetcode-cn.com/ ,如果你热爱编码,热爱算法,该网站一定适合你。
来源:oschina
链接:https://my.oschina.net/u/4340477/blog/3333484