Create Solution.java
parent
d589c45e45
commit
e27cb1fb87
|
|
@ -0,0 +1,405 @@
|
|||
package com.nbee.solution.solution;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Solution {
|
||||
|
||||
//给定一个字符串 s ,找出其中不含有重复字符的 最长子串 的长度。
|
||||
public static int lengthOfLongestSubstring(String s) {
|
||||
// 哈希集合,记录每个字符是否出现过
|
||||
Set<Character> occ = new HashSet<Character>();
|
||||
int n = s.length();
|
||||
// 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
|
||||
int rk = -1, ans = 0;
|
||||
for (int i = 0; i < n; ++i) {
|
||||
if (i != 0) {
|
||||
// 左指针向右移动一格,移除一个字符
|
||||
occ.remove(s.charAt(i - 1));
|
||||
}
|
||||
while (rk + 1 < n && !occ.contains(s.charAt(rk + 1))) {
|
||||
// 不断地移动右指针
|
||||
occ.add(s.charAt(rk + 1));
|
||||
++rk;
|
||||
}
|
||||
// 第 i 到 rk 个字符是一个极长的无重复字符子串
|
||||
ans = Math.max(ans, rk - i + 1);
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
//计算最大价格
|
||||
public static int maxProfit(int[] prices) {
|
||||
if (prices == null || prices.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int minPrice = prices[0];
|
||||
int maxProfit = 0;
|
||||
|
||||
for (int price : prices) {
|
||||
// 更新最小价格
|
||||
minPrice = Math.min(minPrice, price);
|
||||
|
||||
// 计算当前价格的潜在利润并更新最大利润
|
||||
int potentialProfit = price - minPrice;
|
||||
maxProfit = Math.max(maxProfit, potentialProfit);
|
||||
}
|
||||
|
||||
return maxProfit;
|
||||
}
|
||||
|
||||
|
||||
//哈希映射算法(Hash Mapping Algorithm)用于找出一个数组中的众数(majority element)
|
||||
public static int majorityElement(int[] nums) {
|
||||
Map<Integer, Integer> map = new HashMap<>();
|
||||
// maxNum 表示元素,maxCount 表示元素出现的次数
|
||||
int maxNum = 0, maxCount = 0;
|
||||
for (int num: nums) {
|
||||
int count = map.getOrDefault(num, 0) + 1;
|
||||
map.put(num, count);
|
||||
if (count > maxCount) {
|
||||
maxCount = count;
|
||||
maxNum = num;
|
||||
}
|
||||
}
|
||||
return maxNum;
|
||||
}
|
||||
//摩尔投票算法(Boyer-Moore Voting Algorithm)来找出数组中的众数
|
||||
public static int majorityElement1(int[] nums) {
|
||||
int candidate = nums[0], count = 1;
|
||||
for (int i = 1; i < nums.length; ++i) {
|
||||
if (count == 0) {
|
||||
candidate = nums[i];
|
||||
count = 1;
|
||||
} else if (nums[i] == candidate) {
|
||||
count++;
|
||||
} else{
|
||||
count--;
|
||||
}
|
||||
}
|
||||
return candidate;
|
||||
}
|
||||
//合并数组冒泡排序实现
|
||||
public static void merge(int[] nums1, int m, int[] nums2, int n) {
|
||||
System.arraycopy(nums2, 0, nums1, m, n);
|
||||
// 冒泡排序
|
||||
for (int i = 0; i < nums1.length; i++) {
|
||||
for (int j = 0; j < nums1.length; j++) {
|
||||
if (i != j) {
|
||||
if (nums1[i] < nums1[j]){
|
||||
int temp = nums1[i];
|
||||
nums1[i] = nums1[j];
|
||||
nums1[j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
String result = Arrays.stream(nums1).mapToObj(String::valueOf).collect(Collectors.joining(",", "[", "]"));
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
// public static String longestCommonPrefix(String[] strs) {
|
||||
// int index = 0;
|
||||
// StringBuilder temp = new StringBuilder();
|
||||
// if (strs != null){
|
||||
// for (int k = 0; k < strs[0].length(); k++) {
|
||||
// char indexChar = strs[0].charAt(index);
|
||||
// if (strs.length == 1){
|
||||
// return strs[0];
|
||||
// }
|
||||
// for (int i = 1; i < strs.length; i++) {
|
||||
// if (strs[i] != ""){
|
||||
// for (int j = 0; j < 1; j++) {
|
||||
// if (index >= strs[i].length()){
|
||||
// return String.valueOf(temp);
|
||||
// }
|
||||
// char crrChar = strs[i].charAt(index);
|
||||
// if (indexChar != crrChar){
|
||||
// return String.valueOf(temp);
|
||||
// }
|
||||
// if (i == strs.length- 1){
|
||||
// temp.append(crrChar);
|
||||
// index++;
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// return "";
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return String.valueOf(temp);
|
||||
// }
|
||||
// return "";
|
||||
// }
|
||||
|
||||
/**
|
||||
* 编写一个函数来查找字符串数组中的最长公共前缀。
|
||||
* 如果不存在公共前缀,返回空字符串 ""。
|
||||
* @param strs 数组
|
||||
* @return 最长公共前缀
|
||||
*/
|
||||
public static String longestCommonPrefix(String[] strs) {
|
||||
if (strs == null || strs.length == 0) {
|
||||
return "";
|
||||
}
|
||||
int length = strs[0].length();
|
||||
int count = strs.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
char c = strs[0].charAt(i);
|
||||
for (int j = 1; j < count; j++) {
|
||||
if (i == strs[j].length() || strs[j].charAt(i) != c) {
|
||||
return strs[0].substring(0, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return strs[0];
|
||||
}
|
||||
/**
|
||||
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
|
||||
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
|
||||
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
|
||||
*/
|
||||
public static int removeElement(int[] nums, int val) {
|
||||
int i = 0;
|
||||
for (int j = 0; j < nums.length; j++) {
|
||||
if (nums[j] != val) {
|
||||
nums[i] = nums[j];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
/**
|
||||
* 给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。
|
||||
* 元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。
|
||||
*/
|
||||
public static int removeDuplicates(int[] nums) {
|
||||
if (nums.length == 0) return 0;
|
||||
int i = 1; // 从第二个元素开始检查
|
||||
for (int j = 1; j < nums.length; j++) {
|
||||
if (nums[j] != nums[j - 1]) {
|
||||
nums[i] = nums[j];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。
|
||||
* 判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。
|
||||
* @param nums
|
||||
* @return
|
||||
*/
|
||||
public static boolean canJump(int[] nums) {
|
||||
int maxReach = 0; // 初始化最远可到达的位置为0
|
||||
|
||||
for (int i = 0; i < nums.length; i++) {
|
||||
if (i > maxReach) {
|
||||
// 如果当前索引超过了最远可到达的位置,说明无法到达终点
|
||||
return false;
|
||||
}
|
||||
// 更新最远可到达的位置
|
||||
maxReach = Math.max(maxReach, i + nums[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
|
||||
* @param list1
|
||||
* @param list2
|
||||
* @return
|
||||
*/
|
||||
public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
|
||||
ListNode dummy = new ListNode(0);
|
||||
ListNode current = dummy;
|
||||
while (list1 != null && list2 != null) {
|
||||
if (list1.val < list2.val) {
|
||||
current.next = list1;
|
||||
list1 = list1.next;
|
||||
} else {
|
||||
current.next = list2;
|
||||
list2 = list2.next;
|
||||
}
|
||||
current = current.next;
|
||||
}
|
||||
if (list1 != null){
|
||||
current.next = list1;
|
||||
} else if (list2 != null){
|
||||
current.next = list2;
|
||||
}
|
||||
return dummy.next;
|
||||
}
|
||||
|
||||
/**
|
||||
*给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回 -1 。
|
||||
* @param haystack
|
||||
* @param needle
|
||||
* @return
|
||||
*/
|
||||
|
||||
public int strStr(String haystack, String needle) {
|
||||
if (needle.isEmpty()) return -1;
|
||||
return haystack.indexOf(needle);
|
||||
}
|
||||
|
||||
/**
|
||||
* 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
|
||||
*
|
||||
* 请必须使用时间复杂度为 O(log n) 的算法。
|
||||
* @param nums
|
||||
* @param target
|
||||
* @return
|
||||
*/
|
||||
public int searchInsert(int[] nums, int target) {
|
||||
if (nums.length == 0) return 0;
|
||||
for (int i = 0; i < nums.length; i++) {
|
||||
if (nums[i] >= target) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return nums.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。
|
||||
*
|
||||
* 单词 是指仅由字母组成、不包含任何空格字符的最大子字符串。
|
||||
* @param s
|
||||
* @return
|
||||
*/
|
||||
public int lengthOfLastWord(String s) {
|
||||
if (s.isEmpty()) return 0;
|
||||
for (int i = s.length() - 1; i >= 0; i--) {
|
||||
if (s.charAt(i) != ' ') {
|
||||
int count = 0;
|
||||
while (i >= 0 && s.charAt(i) != ' ') {
|
||||
count++;
|
||||
i--;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。
|
||||
*
|
||||
* 最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。
|
||||
*
|
||||
* 你可以假设除了整数 0 之外,这个整数不会以零开头。
|
||||
* @param digits
|
||||
* @return
|
||||
*/
|
||||
public static int[] plusOne(int[] digits) {
|
||||
int n = digits.length;
|
||||
|
||||
// 从数组的最后一位开始处理进位
|
||||
for (int i = n - 1; i >= 0; i--) {
|
||||
if (digits[i] < 9) {
|
||||
digits[i]++;
|
||||
return digits;
|
||||
}
|
||||
// 如果当前位是9,则将其置为0
|
||||
digits[i] = 0;
|
||||
}
|
||||
|
||||
// 如果所有的数字都是9,那么会到这里
|
||||
// 创建一个新的数组,其长度比原数组多1
|
||||
int[] newNumber = new int[n + 1];
|
||||
newNumber[0] = 1;
|
||||
|
||||
return newNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* 给你两个二进制字符串 a 和 b ,以二进制字符串的形式返回它们的和。
|
||||
*
|
||||
* 输入为 非空 字符串且只包含数字 1 和 0。
|
||||
* @param a
|
||||
* @param b
|
||||
* @return
|
||||
*/
|
||||
public static String addBinary(String a, String b) {
|
||||
StringBuilder result = new StringBuilder(); // 用于存储结果
|
||||
int carry = 0; // 进位
|
||||
int i = a.length() - 1, j = b.length() - 1; // 指向字符串a和b的最后一位
|
||||
|
||||
// 当i或j在范围内,或有进位时,继续循环
|
||||
while (i >= 0 || j >= 0 || carry == 1) {
|
||||
int sum = carry; // 当前位的和,初始为进位
|
||||
|
||||
// 如果i在范围内,加上a的当前位
|
||||
if (i >= 0) {
|
||||
sum += a.charAt(i) - '0'; // 将字符转换为数字
|
||||
i--; // 移动到下一位
|
||||
}
|
||||
|
||||
// 如果j在范围内,加上b的当前位
|
||||
if (j >= 0) {
|
||||
sum += b.charAt(j) - '0'; // 将字符转换为数字
|
||||
j--; // 移动到下一位
|
||||
}
|
||||
|
||||
result.append(sum % 2); // 当前位的结果
|
||||
carry = sum / 2; // 更新进位
|
||||
}
|
||||
|
||||
return result.reverse().toString(); // 反转结果并返回
|
||||
}
|
||||
|
||||
/**
|
||||
*给你一个非负整数 x ,计算并返回 x 的 算术平方根 。
|
||||
* 由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
|
||||
* 注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。
|
||||
*
|
||||
* @param x
|
||||
* @return
|
||||
*/
|
||||
public static int mySqrt(int x) {
|
||||
if (x < 2){
|
||||
return x;
|
||||
}
|
||||
long guess = x / 2;
|
||||
while (guess * guess > x){
|
||||
guess = (guess + x/guess)/2;
|
||||
}
|
||||
return (int) guess;
|
||||
}
|
||||
|
||||
/**
|
||||
* 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
|
||||
* 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
|
||||
* @param n
|
||||
* @return
|
||||
*/
|
||||
public static int climbStairs(int n) {
|
||||
if(n < 3)return n;
|
||||
int dp[]=new int[n+1];
|
||||
dp[1]=1;
|
||||
dp[2]=2;
|
||||
for(int i=3;i<n+1;i++) {
|
||||
dp[i]=dp[i-1]+dp[i-2];
|
||||
}
|
||||
return dp[n];
|
||||
}
|
||||
|
||||
/**
|
||||
* 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
|
||||
* @param head
|
||||
* @return
|
||||
*/
|
||||
public static ListNode deleteDuplicates(ListNode head) {
|
||||
ListNode current = head;
|
||||
while (current!= null && current.next != null){
|
||||
if (current.val == current.next.val){
|
||||
current.next = current.next.next;
|
||||
}else {
|
||||
current = current.next;
|
||||
}
|
||||
}
|
||||
return head;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue