目录
1.HJ5进制转换,16变10
JAVA实现16进制转10进制_java十六进制转十进制_奥特曼下象棋的博客-CSDN博客
2.HJ3去除重复数
明明的随机数【Java】_小明的随机数_小明丶的博客-CSDN博客
3.HJ10 字符个数统计
【java算法】HJ10 字符个数统计_lucky__cc的博客-CSDN博客
4.NC61两数之和
牛客 NC61 两数之和(Java 哈希表) - Jolyne123 - 博客园 (cnblogs.com)
5.NC68跳台阶
一、字符串操作
1.HJ17坐标移动
import java.util.*;
import java.io.*;
public class Main{
public static void main(String[] args) throws IOException {
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
String[] in = bf.readLine().split(";");
int x = 0;
int y = 0;
for(String s : in){
// 不满足题目给定坐标规则
if(!s.matches("[WASD][0-9]{1,2}")){
continue;
}
int val = Integer.valueOf(s.substring(1));
switch(s.charAt(0)){
case 'W':
y += val;
break;
case 'S':
y -= val;
break;
case 'A':
x -= val;
break;
case 'D':
x += val;
break;
}
}
System.out.println(x+","+y);
}
}
2.HJ20.密码验证合格程序
import java.util.*;
import java.util.regex.*;
public class Main{
public static void main(String[] arg){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String str = sc.next();
if(str.length() <= 8){
System.out.println("NG");
continue;
}
if(getMatch(str)){
System.out.println("NG");
continue;
}
if(getString(str, 0, 3)){
System.out.println("NG");
continue;
}
System.out.println("OK");
}
}
// 校验是否有重复子串
private static boolean getString(String str, int l, int r) {
if (r >= str.length()) {
return false;
}
if (str.substring(r).contains(str.substring(l, r))) {
return true;
} else {
return getString(str,l+1,r+1);
}
}
// 检查是否满足正则
private static boolean getMatch(String str){
int count = 0;
Pattern p1 = Pattern.compile("[A-Z]");
if(p1.matcher(str).find()){
count++;
}
Pattern p2 = Pattern.compile("[a-z]");
if(p2.matcher(str).find()){
count++;
}
Pattern p3 = Pattern.compile("[0-9]");
if(p3.matcher(str).find()){
count++;
}
Pattern p4 = Pattern.compile("[^a-zA-Z0-9]");
if(p4.matcher(str).find()){
count++;
}
if(count >= 3){
return false;
}else{
return true;
}
}
}
3.*HJ23.删除字符串中出现次数最少的字符
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String s = sc.nextLine();
char[] c = s.toCharArray();
//统计每个字母的数量
HashMap<Character, Integer> map = new HashMap<>();
for (char aChar : c) {
map.put(aChar, (map.getOrDefault(aChar, 0) + 1));
}
//找到数量最少的字符数量
Collection<Integer> values = map.values();
Integer min = Collections.min(values);
//用空字符串替换该字母
for (Character character : map.keySet()) {
if (map.get(character) == min){
s = s.replaceAll(String.valueOf(character), "");
}
}
System.out.println(s);
}
}
}
4.)*HJ33.整数与IP地址间的转换
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String str = sc.next();
// ipv4 -> int
if (str.contains(".")) {
String[] fields = str.split("\\.");
long result = 0;
for (int i = 0; i < 4; i++) {
result = result * 256 + Integer.parseInt(fields[i]);
}
System.out.println(result);
}
// int -> ipv4
else {
long ipv4 = Long.parseLong(str);
String result = "";
for (int i = 0; i < 4; i++) {
result = ipv4 % 256 + "." + result;
ipv4 /= 256;
}
System.out.println(result.substring(0, result.length() - 1));
}
}
}
}
5.HJ101.输入整型数组和排序标识
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) { // 注意 while 处理多个 case
int n = in.nextInt();//接收数组长度
int[] a = new int[n];//创建数组
for (int i = 0; i < n; i++) {//数组填入
a[i] = in.nextInt();
}
int flag = in.nextInt();//接收排序标识
Arrays.sort(a);//数组排序
if(flag==0){
for(int i =0; i < a.length; i++)
System.out.print(a[i] + " ");
}else{
for(int i=a.length-1;i>=0;i--)
System.out.print(a[i]+" ");
}
}
}
}
6.*HJ106.字符串逆序
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNextLine()) {
String str = sc.nextLine();
StringBuilder res = new StringBuilder(str);
System.out.println(res.reverse().toString());
}
}
}
7.leetcode 1839 最长子字符串
解法3贪心算法效率更优。
8.HJ46 截取字符串
System.out.println(s.substring(0,N));
二、排序
1.)HJ8.合并表记录
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
TreeMap<Integer,Integer> map=new TreeMap<>();
while(sc.hasNextInt()){
int n=sc.nextInt();
for(int i=0;i<n;i++){
int k=sc.nextInt();
int v=sc.nextInt();
map.put(k,map.getOrDefault(k,0)+v);
}
for(Integer i:map.keySet()){
System.out.println(i+" "+map.get(i));
}
}
}
}
2.*HJ14.字符串排序
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n=sc.nextInt();
String a[]=new String[n];
for(int i=0;i<n;i++){
a[i]=sc.next();
}
Arrays.sort(a);
for(String str:a){
System.out.println(str);
}
}
}
3.HJ27.查找兄弟单词
import java.util.*;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String s[]=sc.nextLine().split(" ");
Integer n=Integer.parseInt(s[0]);
String find=s[s.length-2];
Integer k=Integer.parseInt(s[s.length-1]);
List<String> list=new ArrayList<>();
for(int i=1;i<=n;i++){
if(isBro(find,s[i])){
list.add(s[i]);
}
}
int size=list.size();
System.out.println(size);
if(size>=k){
Collections.sort(list);
System.out.println(list.get(k-1));
}
}
}
public static boolean isBro(String x,String y){
if (x.length()!=y.length()||y.equals(x)){
return false;
}
char[] s = x.toCharArray();
char[] j= y.toCharArray();
Arrays.sort(s);
Arrays.sort(j);
return new String(s).equals(new String(j));
}
}
4.*NC37.合并区间
import java.util.*;
public class Solution {
public ArrayList<Interval> merge(ArrayList<Interval> intervals){
ArrayList<Interval> res=new ArrayList<>();
//
if(intervals.size()==0)
return res;
//重载比较,按照区间首排序
Collections.sort(intervals,new Comparator<Interval>(){
public int compare(Interval o1, Interval o2){
if(o1.start!=o2.start)
return o1.start-o2.start;
else
return o1.end-o2.end;
}
});
//放入第一个区间
res.add(intervals.get(0));
int count=0;
//遍历后续区间,查看是否与末尾有重叠
for(int i = 1; i < intervals.size(); i++){
Interval o1 = intervals.get(i);
Interval origin = res.get(count);
if(o1.start > origin.end){
res.add(o1);
count++;
}else{
res.remove(count);
Interval s = new Interval(origin.start, o1.end);
if(o1.end < origin.end)
s.end = origin.end;
res.add(s);
}
}
return res;
}
}
具体做法:
step 1:既然要求重叠后的区间按照起点位置升序排列,我们就将所有区间按照起点位置先进行排序。使用sort函数进行排序,重载比较方式为比较interval结构的start变量。
step 2:排序后的第一个区间一定是起点值最小的区间,我们将其计入返回数组res,然后遍历后续区间。
step 3:后续遍历过程中,如果遇到起点值小于res中最后一个区间的末尾值的情况,那一定是重叠,取二者最大末尾值更新res中最后一个区间即可。
step 4:如果遇到起点值大于res中最后一个区间的末尾值的情况,那一定没有重叠,后续也不会有这个末尾的重叠区间了,因为后面的起点只会更大,因此可以将它加入res。
复杂度分析:
- 时间复杂度:O(nlog2n),排序的复杂度为O(nlog2n),后续遍历所有区间的复杂度为O(n),属于低次幂,忽略
- 空间复杂度:O(1),res为返回必要空间,没有使用额外辅助空间
5.*HJ68.成绩排序
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
HashMap<Integer,String> map = new HashMap<>();
// 注意 hasNext 和 hasNextLine 的区别
while (sc.hasNextLine()) {
int n=Integer.parseInt(sc.nextLine());
int flag=Integer.parseInt(sc.nextLine());//1 0
int[][] grades=new int[n][2];//
for(int i=0;i<n;i++){
String[] NameAndScore=sc.nextLine().split("\\s+");
grades[i][0]=i;
grades[i][1] = Integer.parseInt(NameAndScore[1]);
map.put(i,NameAndScore[0]);
}
Arrays.sort(grades,(o1,o2)->{
if(flag==0){
return o2[1]-o1[1];
}else{
return o1[1]-o2[1];
}
});
for(int i=0;i<n;i++)
System.out.println(map.get(grades[i][0])+" "+grades[i][1]);
}
}
}
Java使用lambda自定义Arrays.sort排序规则说明_java_脚本之家 (jb51.net)
三、栈
1.NC52.括号序列
import java.util.*;
public class Solution {
public boolean isValid (String s) {
//辅助栈
Stack<Character> st=new Stack<>();
for(int i=0;i<s.length();i++){
if(s.charAt(i)=='(')
st.push(')');
else if(s.charAt(i) == '[')
st.push(']');
else if(s.charAt(i) == '{')
st.push('}');
//必须有左括号的情况下才能遇到右括号
else if(st.isEmpty() || st.pop() != s.charAt(i))
return false;
}
//栈中是否还有元素
return st.isEmpty();
}
}
复杂度分析:
时间复杂度:O(n),其中n为字符串长度,遍历整个字符串
空间复杂度:O(n),最坏情况下栈空间中记录整个字符串长度的右括号
2.*leetcode 1614.括号的最大嵌套深度
方法一:遍历
对于括号计算类题目,我们往往可以用栈来思考。
遍历字符串 s,如果遇到了一个左括号,那么就将其入栈;如果遇到了一个右括号,那么就弹出栈顶的左括号,与该右括号匹配。这一过程中的栈的大小的最大值,即为 s 的嵌套深度。
代码实现时,由于我们只需要考虑栈的大小,我们可以用一个变量size 表示栈的大小,当遇到左括号时就将其加一,遇到右括号时就将其减一,从而表示栈中元素的变化。这一过程中 size 的最大值即为 s 的嵌套深度。
class Solution {
public int maxDepth(String s) {
int ans = 0, size = 0;
for (int i = 0; i < s.length(); ++i) {
char ch = s.charAt(i);
if (ch == '(') {
++size;
ans = Math.max(ans, size);
} else if (ch == ')') {
--size;
}
}
return ans;
}
}
复杂度分析
时间复杂度:O(n),其中 n 是字符串 s 的长度。
空间复杂度:O(1)。我们只需要常数空间来存放若干变量。
四、排列组合
1.*leetcode 面试题08.08.有重复字符串的排列组合
回溯全排列题解。
2.leetcode 77.组合
方法一:递归实现组合型枚举
class Solution {
List<Integer> temp = new ArrayList<Integer>();
List<List<Integer>> ans = new ArrayList<List<Integer>>();
public List<List<Integer>> combine(int n, int k) {
dfs(1, n, k);
return ans;
}
public void dfs(int cur, int n, int k) {
// 剪枝:temp 长度加上区间 [cur, n] 的长度小于 k,不可能构造出长度为 k 的 temp
if (temp.size() + (n - cur + 1) < k) {
return;
}
// 记录合法的答案
if (temp.size() == k) {
ans.add(new ArrayList<Integer>(temp));
return;
}
// 考虑选择当前位置
temp.add(cur);
dfs(cur + 1, n, k);
temp.remove(temp.size() - 1);
// 考虑不选择当前位置
dfs(cur + 1, n, k);
}
}
执行用时:1 ms, 在所有 Java 提交中击败了99.97%的用户
内存消耗:42.8 MB, 在所有 Java 提交中击败了48.55%的用户
复杂度分析
时间复杂度:O(( kn)×k),分析见「思路」部分。
空间复杂度:O(n + k) =O(n),即递归使用栈空间的空间代价和临时数组 temp 的空间代价。
五、双指针
1.*leetcode 674.最长连续递增序列
画解算法解题思路
标签:遍历
过程:
count 为当前元素峰值,ans为最大峰值
初始化 count = 1
从 0 位置开始遍历,遍历时根据前后元素状态判断是否递增,递增则 count++,递减则 count=1
如果 count>ans,则更新 ans
直到循环结束
时间复杂度:O(N)
public int findLengthOfLCIS(int[] nums) {
if(nums.length <= 1)
return nums.length;
int ans = 1;
int count = 1;
for(int i=0;i<nums.length-1;i++) {
if(nums[i+1] > nums[i]) {
count++;
} else {
count = 1;
}
ans = count > ans ? count : ans;
}
return ans;
}
2.NC17.最长回文子串 中心扩展法(推荐使用) 贪心
因为最后一次不满足条件退出循环时,在上一次循环中begin和end的差值已经被扩大了2了,所以实际上是end-begin+1-2,最后是end-begin-1
3.NC28.最小覆盖子串 较难 滑动窗口。。
六、深度搜索
1.HJ41.称砝码
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNextInt()) { // 注意 while 处理多个 case
HashSet<Integer> set = new HashSet<>();
set.add(0);
int N = sc.nextInt();
int[] w = new int[N];
int[] n = new int[N];
for (int i = 0; i < N; i++) {
w[i] = sc.nextInt();//砝码的重量
}
for (int i = 0; i < N; i++) {
n[i] = sc.nextInt();//砝码个数
}
for (int i = 0; i < N; i++) {//遍历砝码
ArrayList<Integer> list=new ArrayList<>(set);//取当前所有的结果
for(int j=1;j<=n[i];j++){//遍历个数
for(int k=0;k<list.size();k++){
set.add(list.get(k)+w[i]*j);
}
}
}
System.out.println(set.size());
}
}
}
七、二叉树
1.*leetcode 剑指offer 32 — II.从上到下打印二叉树 II
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
List<List<Integer>> ans = new ArrayList<>();
if(root != null) queue.add(root);
while(!queue.isEmpty()) {
List<Integer> tmp = new ArrayList<>();
for(int i = queue.size(); i > 0; i--) {
TreeNode node = queue.poll();
tmp.add(node.val);
if(node.left != null) queue.add(node.left);
if(node.right != null) queue.add(node.right);
}
ans.add(tmp);
}
return ans;
}
}
执行用时:0 ms, 在所有 Java 提交中击败了100.00%的用户
内存消耗:41.7 MB, 在所有 Java 提交中击败了30.17%的用户
2.leetcode 剑指offer 32 — III.从上到下打印二叉树 III
参考大佬题解,思路步骤清晰!!!
八、其他
1.*HJ108.求最小公倍数
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNextInt()) { // 注意 while 处理多个 case
int a = in.nextInt();
int b = in.nextInt();
int lcm = a * b / gcd(a, b);
System.out.println(lcm);
}
}
public static int gcd(int a, int b) {
if (b == 0)return a;
return gcd(b, a % b);
}
}
2.*HJ28.素数伴侣 困难
import java.util.*;
public class Main {//这里包含了判断素数的方法
//小技巧!!!素数不是偶数,那么和是素数的话就是奇数+偶数
//那么可以分成两堆,一堆偶数,一堆奇数
//匈牙利算法,先到先得 能让就让
//有机会上,没机会创造机会也要上
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner scan = new Scanner(System.in);
while(scan.hasNext()){
int n = scan.nextInt();
int[] tempArray = new int[n];
for(int i = 0; i < n; i++){
tempArray[i] = scan.nextInt();
}
ArrayList<Integer> evens = new ArrayList<Integer>();
ArrayList<Integer> odds = new ArrayList<Integer>();
for(int i = 0; i < n; i++) {
if((tempArray[i] & 1) != 1) {
evens.add(tempArray[i]);
}else {
odds.add(tempArray[i]);
}
}
//下面开始才是重头戏
//用于标记那个奇数匹配了偶数,直接记录奇数的值,而不是奇数在奇数数组中的下标
int[] evensMatch =new int[evens.size()];
int result = 0;
//遍历奇数去匹配偶数
for(int i = 0; i < odds.size(); i++) {
//每一步重新创建,也就是相当于清空
//used数组用于标记某个某数位置是否
int[] used = new int[evens.size()];
//这里采用了匈牙利算法,先到先得
if(find(odds.get(i), evens, used, evensMatch)) {
result++;
}
}
System.out.println(result);
}
}public static boolean isPrime(int num) {
for(int i = 2; i * i <= num; i++) {
if(num % i == 0) {
return false;
}
if(num == 1) {
return false;
}
}
return true;
}public static boolean find(int x, ArrayList<Integer> evens,int[] used, int[] evensMatch) {
//遍历偶数
//去检查当前传入的奇数能否与偶数哪些数匹配
for(int i = 0; i < evens.size(); i++) {
//如果当前偶数与传入的奇数匹配,并且当前偶数位还没有匹配过奇数
if(isPrime(x + evens.get(i)) && used[i] == 0) {
//设置当前偶数位匹配为true,也就是 1
used[i] = 1;
//如果第i个偶数没有伴侣
//或者第i个偶数原来有伴侣,并且该伴侣能够重新找到伴侣的话(这里有递归调用)
//则奇数x可以设置为第i个偶数的伴侣
//这里采用了匈牙利算法,能让则让
if(evensMatch[i] == 0 || find(evensMatch[i], evens, used, evensMatch)) {
evensMatch[i] = x;
return true;
}
}
}
//遍历完偶数都没有可以与传入奇数做伴侣的,该奇数只能孤独终老了
return false;
}}
n3,n
3.*HJ60.查找组成一个偶数最接近的两个素数
方法二:穷举优化
解题思路:
采取从中间向两边枚举的方式,这样贪心的控制住两素数之差距离最小的这个限制
算法流程:
对于每个数字,从最接近的两个中位数开始处理判断是否素数
如果两个组成偶数的数字都是素数,因为是从最接近的两个数开始枚举,因此一旦都是素数则输出并返回,得到结果
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()){
int num = scanner.nextInt();
solution(num);
}
}
private static void solution(int num) {
//如num=10, 遍历:5,6,7,8
// 从最接近的两个中位数开始处理判断
for(int i = num / 2; i < num - 1; i++) {
if(isPrime(i) && isPrime(num - i)) {
System.out.println((num - i) + "\n" + i);
return;
}
}
}
// 判断是否素数
private static boolean isPrime(int num) {
for(int i = 2; i <= Math.sqrt(num); i++) {
if(num % i == 0) {
return false;
}
}
return true;
}
}
复杂度分析:时间复杂度:NsqrtN ,外循环最多遍历 N/2 次,内循环每个数最多sqrtN
空间复杂度:O(1),只用到常数级别的空间开销
4.*leetcode 994.腐烂的橘子 BFS 层序遍历,可求最短路径
5.leetcode 204.计数质数
方法二:埃氏筛
枚举没有考虑到数与数的关联性,因此难以再继续优化时间复杂度。接下来我们介绍一个常见的算法,该算法由希腊数学家厄拉多塞(\rm EratosthenesEratosthenes)提出,称为厄拉多塞筛法,简称埃氏筛。我们考虑这样一个事实:如果 xx 是质数,那么大于 xx 的 xx 的倍数 2x,3x,\ldots2x,3x,… 一定不是质数,因此我们可以从这里入手。
我们设 \textit{isPrime}[i]isPrime[i] 表示数 ii 是不是质数,如果是质数则为 11,否则为 00。从小到大遍历每个数,如果这个数为质数,则将其所有的倍数都标记为合数(除了该质数本身),即 00,这样在运行结束的时候我们即能知道质数的个数。
这种方法的正确性是比较显然的:这种方法显然不会将质数标记成合数;另一方面,当从小到大遍历到数 xx 时,倘若它是合数,则它一定是某个小于 xx 的质数 yy 的整数倍,故根据此方法的步骤,我们在遍历到 yy 时,就一定会在此时将 xx 标记为 \textit{isPrime}[x]=0isPrime[x]=0。因此,这种方法也不会将合数标记为质数。
当然这里还可以继续优化,对于一个质数 xx,如果按上文说的我们从 2x2x 开始标记其实是冗余的,应该直接从 x\cdot xx⋅x 开始标记,因为 2x,3x,\ldots2x,3x,… 这些数一定在 xx 之前就被其他数的倍数标记过了,例如 22 的所有倍数,33 的所有倍数等。
class Solution {
public int countPrimes(int n) {
int[] isPrime = new int[n];
Arrays.fill(isPrime, 1);
int ans = 0;
for (int i = 2; i < n; ++i) {
if (isPrime[i] == 1) {
ans += 1;
if ((long) i * i < n) {
for (int j = i * i; j < n; j += i) {
isPrime[j] = 0;
}
}
}
}
return ans;
}
}
力扣官方题解多角度多语言,还有延伸面试外的优选方法线性函数。。。
6.HJ25. 数据分类处理 较难
7.HJ29 字符串加解密
超时。。。。。。用映射。。还要加其他不用处理的字符
//tips:大小写转换不用查ASCII码表,通过字符加减就能实现
//有大佬说数字转换可以通过加一再除以十取余数的方式实现,这样不用单独考虑9,方便多了!
//解密函数
private static String decode(String password) {
char[] t = password.toCharArray();
//注意减法要再加一个26或10,才可以正常循环起来
for (int i = 0; i < t.length; i++) {
if (t[i] >= 'a' && t[i] <= 'z') {
t[i] = (char) ((t[i] - 'a' - 1 + 26) % 26 + 'A');
} else if (t[i] >= 'A' && t[i] <= 'Z') {
t[i] = (char) ((t[i] - 'A' - 1 + 26) % 26 + 'a');
} else if (t[i] >= '0' && t[i] <= '9') {
t[i] = (char) ((t[i] - '0' - 1 + 10) % 10 + '0');
}
}
return String.valueOf(t);
}
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
String a = in.nextLine();
String b = in.nextLine();
System.out.println(encrypt(a));
System.out.println(decrypt(b));
}
}
private static char[] mletter = "abcdefghijklmnopqrstuvwxyz".toCharArray();
private static char[] cletter = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();
private static char[] number = "0123456789".toCharArray();
private static String encrypt(String input) {
char[] arr = input.toCharArray();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
int index = (int)arr[i];
if (arr[i] >= 'a' && arr[i] <= 'z') {
builder.append(cletter[(index - 97 + 1) % 26]); // 字母a的int值是97,我们这里减成0后+1然后对26(a-z=26个字母)取模,再去大写数组里找对应下标就是了
} else if (arr[i] >= 'A' && arr[i] <= 'Z') {
builder.append(mletter[(index - 65 + 1) % 26]);
} else if (arr[i] >= '0' && arr[i] <= '9') {
builder.append(number[(index - 48 + 1) % 10]);
} else {
builder.append(arr[i]);
}
}
return builder.toString();
}
private static String decrypt(String input) {
char[] arr = input.toCharArray();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
int index = (int)arr[i];
if (arr[i] >= 'a' && arr[i] <= 'z') {
builder.append(cletter[(index - 97 + 26 - 1) % 26]); // 字母a的int值是97,为了防止负数出现,我们加26后再取模.PS:取模就跟拨时钟一样,12个钟多拨一圈会回到原点;)
} else if (arr[i] >= 'A' && arr[i] <= 'Z') {
builder.append(mletter[(index - 65 + 26 - 1) % 26]);
} else if (arr[i] >= '0' && arr[i] <= '9') {
builder.append(number[(index - 48 + 10 - 1) % 10]);
} else {
builder.append(arr[i]);
}
}
return builder.toString();
}
}
8.剑指 Offer 61. 扑克牌中的顺子
多种思路
class Solution {
public boolean isStraight(int[] nums) {
int joker = 0;
Arrays.sort(nums); // 数组排序
for(int i = 0; i < 4; i++) {
if(nums[i] == 0) joker++; // 统计大小王数量
else if(nums[i] == nums[i + 1]) return false; // 若有重复,提前返回 false
}
return nums[4] - nums[joker] < 5; // 最大牌 - 最小牌 < 5 则可构成顺子
}
}
9.HJ43 迷宫问题 BFS
- offer() 是往队列中添加一个元素,若队列已满而仍往队列中添加,则会返回false
- poll() 是删除队列中的第一个元素,在对空队列进行操作时,返回null
- peek() 是输出队列的第一个元素,队列为空时,返回null
10.leetcode 322. 零钱兑换 ,也可搜索 动态规划相关题型 (技术面试高频考点)
动规力扣
memo[i] 有两种实现的方式,去两者的最小值
包含当前的 coins[i]coins[i],那么剩余钱就是 i-coins[i]i−coins[i],这种操作要兑换的硬币数是 memo[i-coins[j]] + 1memo[i−coins[j]]+1
不包含,要兑换的硬币数是 memo[i]memo[i]
class Solution {
public int coinChange(int[] coins, int amount) {
// 自底向上的动态规划
if(coins.length == 0){
return -1;
}
// memo[n]的值: 表示的凑成总金额为n所需的最少的硬币个数
int[] memo = new int[amount+1];
// 给memo赋初值,最多的硬币数就是全部使用面值1的硬币进行换
// amount + 1 是不可能达到的换取数量,于是使用其进行填充
Arrays.fill(memo,amount+1);
memo[0] = 0;
for(int i = 1; i <= amount;i++){
for(int j = 0;j < coins.length;j++){
if(i - coins[j] >= 0){
// memo[i]有两种实现的方式,
// 一种是包含当前的coins[i],那么剩余钱就是 i-coins[i],这种操作要兑换的硬币数是 memo[i-coins[j]] + 1
// 另一种就是不包含,要兑换的硬币数是memo[i]
memo[i] = Math.min(memo[i],memo[i-coins[j]] + 1);
}
}
}
return memo[amount] == (amount+1) ? -1 : memo[amount];
}
}
11.岛屿问题 leetcode 200 (技术面试高频考点)
我们所熟悉的 DFS(深度优先搜索)问题通常是在树或者图结构上进行的。而我们今天要讨论的 DFS 问题,是在一种「网格」结构中进行的。岛屿问题是这类网格 DFS 问题的典型代表。网格结构要比二叉树结构稍微复杂一些,它其实是一种简化版的图结构。
12.火锅问题