Create Solution.java

This commit is contained in:
2024-07-09 22:45:58 +08:00
parent d589c45e45
commit e27cb1fb87

View File

@@ -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;
}
}