蓝桥云课:
🔣1.最长子序列
题目:
我们称一个字符串 S 包含字符串 T 是指 T是 S的一个子序列,即可以从字符串 S中抽出若干个字符,它们按原来的顺序组合成一个新的字符串与 T完全一样。
给定两个字符串 S和 T,请问 T中从第一个字符开始最长连续多少个字符 被 S包含?
示例
输入
ABCDEABCD
AABZ
输出
3
思路:
双指针:一个对着S,一个对着T,从起始位置开始判断,如果相等,t指针往下走,最后s指针走
code:
import java.util.Scanner;
public class 最长子序列 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
char[] s = sc.next().toCharArray();
char[] t = sc.next().toCharArray();
//双指针 i对着s j对着t
int i = 0;
int j = 0;
while (i < s.length && j < t.length){
if(s[i]==t[j]){
j++;
}
i++;
}
System.out.println(j);
}
}
🔣2.数位排序
题目:
小蓝对一个数的数位之和很感兴趣, 今天他要按照数位之和给数排序。当 两个数各个数位之和不同时, 将数位和较小的排在前面, 当数位之和相等时, 将数值小的排在前面。
例如, 2022 排在 409 前面, 因为 2022 的数位之和是 6, 小于 409 的数位 之和 13 。
又如, 6 排在 2022 前面, 因为它们的数位之和相同, 而 6 小于 2022 。
给定正整数 n, m 请问对 1 到 n采用这种方法排序时, 排在第 m个的元 素是多少?
思路:
对数位和进行分组,也就是数位和为1是一组,并将其里面元素排序,数位和为2的元素为一组,并将其里面的数据排序以此类推。因为形成一对多的情况,采用哈希表(Map映射)。
code:
import java.util.*;
public class 数位排序 {
//Key Integer Value 集合
static Map<Integer, List<Integer>> map = new HashMap<>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int m = sc.nextInt();
//进行分组,数位和是1.存的都是1
for (int i = 1; i <= n; i++) {
add(check(i), i);
}
//获得 Key 的集合
List<Integer> list = new ArrayList<>(map.keySet());
//排序
Collections.sort(list);
for (Integer integer : list) {
//获取当前集合里面的数位和
List<Integer> q = map.get(integer);
if (m > q.size()) {
m -= q.size();
continue;
}
Collections.sort(q);
System.out.println(q.get(m - 1));
break;
}
}
//封装函数
//作用 往 第a个list存入b
public static void add(int a, int b) {
if (!map.containsKey(a)) {
map.put(a, new ArrayList<>());
}
//把元素b放入到结合a
map.get(a).add(b);
}
//数位和
public static int check(Integer x) {
int res = 0;
while (x != 0) {
res += x % 10;
x = x / 10;
}
return res;
}
}
🔣3.子串分值和
题目:
对于一个字符串 S,我们定义 S 的分值 f(S) 为 S 中出现的不同的字符个数。例如 f(“aba”) = 2,f(“abc”) = 3, f(“aaa”) = 1f(“aba”)=2,f(“abc”)=3,f(“aaa”)=1。
现在给定一个字符串 S [0…n − 1]S[0…n−1](长度为 nn),请你计算对于所有 SS 的非空子串 S [i…j](0 ≤ i ≤ j < n)Si…j,f(S [i…j])f(S[i…j]) 的和是多少。
思路:
贡献思想,比如前面没有a,a第一次出现贡献最大,一分 例如:…a… 就有4 x 4=16种情况(包括不选)
当前位置 i 减 上次出现的位置(s[i] - ‘a’) 乘以 n-当前位置 i
将字符串转为字符数组,因为字符串只要求大写字母,所以开一个26大小的数组last,先将last全部填充为-1,
code:
import java.util.Arrays;
import java.util.Scanner;
public class 子串分值和 {
static int[] last = new int[26];
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
char[] s = sc.next().toCharArray();
long ans = 0;
int n = s.length;
Arrays.fill(last, -1);
for (int i = 0; i < n; i++) {
ans += (long) (i - last[s[i] - 'a']) * (n - i);
last[s[i] - 'a'] = i;
}
System.out.println(ans);
}
}
Leetcode:
🔣1.差值
题目:
给你一个整数 n,请你帮忙计算并返回该整数「各位数字之积」与「各位数字之和」的差。
输入:n = 234
输出:15
解释:
各位数之积 = 2 * 3 * 4 = 24
各位数之和 = 2 + 3 + 4 = 9
结果 = 24 - 9 = 15
思路:
分别计算 数位积 和 数位和 做差即可。
code:
import java.util.Scanner;
public class Test1281 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
System.out.println(subtractProductAndSum(n));
}
public static int subtractProductAndSum(int n) {
return ji(n) - check(n);
}
public static int check(int x) {
int ans = 0;
while (x != 0) {
ans += x % 10;
x /= 10;
}
return ans;
}
public static int ji(int x) {
int ans = 1;
while (x != 0) {
ans *= x % 10;
x /= 10;
}
return ans;
}
}
🔣2.两数之和
题目:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 **和为目标值 **target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
思路:
哈希表(Map映射)
A + B = target,A就是nums[i],那么B就是 target - nums[i]。遍历数组,如果存在B,直接返回B,i,两个都是索引,否则,添加到哈希表中。
code:
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class Test1 {
public static void main(String[] args) {
int[] nums = {2, 7, 11, 15};
System.out.println(Arrays.toString(twosum(nums, 9)));
}
public static int[] twosum(int[] nums, int target) {
Map<Integer,Integer> hashmap=new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if(hashmap.containsKey(target-nums[i])){
return new int[]{hashmap.get(target-nums[i]),i};
}
hashmap.put(nums[i],i);
}
return new int[0];
}
}
🔣3.寻找旋转排序数组中的最小值
题目:
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
- 若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
- 若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]
注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。
给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。
输入:nums = [3,4,5,1,2]
输出:1
解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。
思路:
二分:根据二段性,因为是升序在进行翻转,所以从某个地方分开,两边都是递增的.我判断nums[mid]与nums[right]大小,如果nums[mid]>nums[right],更改左边区间(即不要左边区间),left来到mid+1区间 left=mid+1,否则更改右边区间,right来到mid位置。最后返回nums[left]的值,就是最小值。
code:
class Solution {
public int findMin(int[] nums) {
int l=0;
int r=nums.length-1;
while(l<r){
int mid=l+(r-l)/2;
if(nums[mid]>nums[r]){
l=mid+1;
}else r=mid;
}
return nums[l];
}
}
🔣4.寻找峰值
题目:
峰值元素是指其值严格大于左右相邻值的元素。
给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞ 。
你必须实现时间复杂度为 O(log n)_ _的算法来解决此问题。
输入:nums = [1,2,3,1]
输出:2
解释:3 是峰值元素,你的函数应该返回其索引 2。
思路:
二分:因为是山峰数组,所以必然整个区间有最大值mid,而且nums[mid]大于nums[mid-1]和nums[mid]>nums[mid+1],所以我们只需要判断nums[mid]如果大于nums[mid+1]的话舍去右边区间,因为右边不会在比mid+1大了已经,此时right来到mid位置 r= mid;否则 left 来到 mid+1的位置
l=left+1;最后返回left。
code:
class Solution {
public int findPeakElement(int[] nums) {
if(nums.length==1){
return 0;
}
int l=0;
int r=nums.length-1;
while(l<r){
int mid=l+(r-l)/2;
if(nums[mid]>nums[mid+1]){
r=mid;
}else l=mid+1;
}
return l;
}
}