喝汽水
两瓶即可换一瓶
import java.util.*;
public class Main {
public static void main(String[] args) {
//剩2个空瓶子时,可以先找老板借一瓶汽水,喝掉这瓶满的,喝完以后用3个空瓶子换一瓶满的还给老板。
//也就是说2个空瓶子即可换一瓶汽水喝,而且喝完之后手里也没有空瓶子。
Scanner in = new Scanner(System.in);
//f[i] = f[i/3+i%3]+i/3 看 f[i/3+i%3]能对多少
int dp[] = new int[101];
dp[0] = 0;
dp[1] = 1;
dp[2] = 1;
dp[3] = 1;
dp[4] = 2;
int index = 5;
for (; index <= 100; index++) {
dp[index] = dp[index / 3 + index % 3 ] + index / 3;
}
while (in.hasNext()) {
int x = in.nextInt();
if (x == 0) return;
System.out.println(dp[x]);
}
}
}
兔子问题,兔子不死,两个月就长大,生兔子。
f[i] = f[i-1]+f[i-2]; 斐波那契数列
杨辉三角变形 - 推规律
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XsI2JW7Z-1690389939897)(https://s2.loli.net/2022/07/09/GIQbhajw3EAfvVB.png)]
放苹果
n个苹果放m哥盘子,问有多少种放法,可以空盘。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
//dp[i][j] 表示i个苹果放 j个盘子的方案书
// dp[i][j] = dp[i][j-1] 表示j个盘子忽略 (i<j)时候一定有空盘子,其方案书就等于 dp[i][i] 相当于空盘子不用管
//dp[i][j] = dp[i-j][j] 表示j个盘子,每个盘子放1个后,再去划分i-j个橘子
int n ,m;
n = in.nextInt();
m = in.nextInt();
int dp[][] = new int [n+1][m+1];
for(int i=0;i<=m;i++) dp[0][i] = 1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i<j) dp[i][j] = dp[i][j-1];
else{
dp[i][j] = dp[i][j-1]+dp[i-j][j];
}
}
}
System.out.println(dp[n][m]);
}
}
合唱队
N位同学站成一排,音乐老师要请其中的(N-K)位同学出列,使得剩下的K位同学排成合唱队形。
合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2…,K,他们的身高分别为T1,T2,…,TK, 则他们的身高满足存在i(1<=i<=K)使得T1<T2<…<Ti-1 <Ti+1&& Ti+1>…>TK。
你的任务是,已知所有N位同学的身高,计算最少需要几位同学出列,可以使得剩下的同学排成合唱队形.
两个dp,记录从左往右或者从右往左的最长上升子序列,dp[i]是包含i在内的最长上升子序列长度。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = null;
int n = Integer.parseInt(br.readLine());
str = br.readLine();
int [] arr = Arrays.stream(str.split(" ")).mapToInt(
Integer::parseInt).toArray();
int left [] = new int [arr.length];
int right [] = new int [arr.length];
int len = arr.length;
left[0] = 1;
right[len - 1] = 1;
//left[i]表示从左往右遍历前i个人(包括第i个人在内) 递增子序列的长度,这点很重要,
//最后计算的时候 left[i]+right[i] -1 减1是减去那个重复的第i个人。
//right[i] 下标i右边的递增子序列
for (int i = 1; i < len; i++) {
left[i] =1;
for (int j = 0; j < i; j++) {
if (arr[j] < arr[i]) left[i] = Math.max(left[j] + 1,left[i]);
}
}
for (int i = len - 2; i >= 0; i--) {
right[i]=1;
for (int j = len - 1; j > i; j--) {
if (arr[j] < arr[i]) right[i] = Math.max(right[j] + 1,right[i]);
}
}
int max = 0;
for (int i = 0; i < len; i++) {
if (left[i] + right[i]-1 > max) {
max = left[i] + right[i]-1;
}
//System.out.println(left[i]+" "+right[i]);
}
System.out.println(len-max);
}
}
字符串排序
编写一个程序,将输入字符串中的字符按如下规则排序。
规则 1 :英文字母从 A 到 Z 排列,不区分大小写。
如,输入: Type 输出: epTy
规则 2 :同一个英文字母的大小写同时存在时,按照输入顺序排列。
如,输入: BabA 输出: aABb
规则 3 :非英文字母的其它字符保持原来的位置。
如,输入: By?e 输出: Be?y
数据范围:输入的字符串长度满足 1≤n≤1000 1≤n≤1000
根据字典序(26个字母)从左往右遍历元素,元素是对应字典序,就摘选元素进行输出,既考虑元素输入循序,也考虑了字典序。
import java.util.*;
public class Main{
public static void main(String a[]){
Scanner in = new Scanner (System.in);
String str = in.nextLine();
char chs[] = str.toCharArray();
ArrayList<Character> list = new ArrayList<>();
//排序 主要看的排序的稳定性,对于其他字符不进行swap即可。其他元素交换。
// 注意稳定性
int len = chs.length;
//基数排序
for(int i=0;i<26;i++){
for(int j=0;j<len;j++){
if(chs[j]-'a'==i||chs[j]-'A'==i){
list.add(chs[j]);
}
}
}
//
for(int i=0,k=0;(i<len)&&k<list.size();i++){
if((chs[i]>='a'&&chs[i]<='z')||(chs[i]>='A'&&chs[i]<='Z')){
chs[i] = list.get(k++);
}
}
System.out.println(new String(chs));
}
}
密码截取
求最长回文串,中心拓展。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;
//最长回文串
str = br.readLine();
str = process(str);
int max = 1;
char arr[] = str.toCharArray();
for(int i=0;i<str.length();i++){
int t = spread(i,arr);
if(max<t) max = t;
}
System.out.println(max-1);
}
static int spread(int x, char [] arr) {
int left = x - 1, right = x + 1;
int count = 1;
while (left >= 0 && right < arr.length) {
if (arr[left] == arr[right])
count++;
else break;
left--;
right++;
}
return count;
}
static String process(String str) {
StringBuilder bu = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
bu.append("#" + str.charAt(i));
}
bu.append("#");
return bu.toString();
}
}
称砝码-求种数
import java.util.*;
public class Main {
public static void main(String s[]) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m[] = new int[n];
int x[] = new int[n];
int sum = 0;
for (int i = 0; i < n; i++) {
m[i] = in.nextInt();
}
for (int i = 0; i < n; i++) {
x[i] = in.nextInt();
sum += m[i] * x[i];
}
boolean dp[] = new boolean [sum + 1];
// System.out.println(dp[sum]);
dp[0] = true;
//保证第i件物品只用j次
for (int i = 0; i < n; i++) {
for (int j = 0; j < x[i]; j++) {
for (int k = sum; k >=m[i]; k--) {
if(dp[k-m[i]]) dp[k] = true;
}
}
}
int count = 0;
for (int i = 0; i <= sum; i++) {
// if(dp[i]) System.out.println(i+" "+dp[i]);
if (dp[i]) count++;
}
System.out.println(count);
}
}
迷宫-求路径
- 唯一解,起点左上角,终点右下角,那就dfs,优先往下、往右走,没走一步将原有的路径封闭,表示已经走过,且将试探的下一步路径放入队列尾部,直到找到终点或者无路可走那就将队列尾部节点出队,表示该节点已经是死路。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
// import java.util.Stack;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str1 = br.readLine();
int n = Integer.parseInt(str1.split(" ")[0]);
int m = Integer.parseInt(str1.split(" ")[1]);
int maze [][] = new int [n][m];
for (int i = 0; i < n; i++) {
str1 = br.readLine();
int a[] = Arrays.stream(str1.split(" ")).mapToInt(Integer::parseInt).toArray();
for (int j = 0; j < m; j++)
maze[i][j] = a[j];
}
LinkedList<Node> stack = new LinkedList<>();
stack.push(new Node(0, 0));
boolean [][] isVisit = new boolean [n][m];
while (!stack.isEmpty()) {
Node node = stack.peek();
if (node.x == n - 1 && node.y == m - 1) break;
visit(node, maze, stack);
}
while (!stack.isEmpty()) {
Node node = stack.removeLast();
System.out.println("(" + node.x + "," + node.y + ")");
}
}
static void visit(Node node, int maze[][], LinkedList stack) {
int n = maze.length;
int m = maze[0].length;
int x = node.x;
int y = node.y;
if (x < n - 1 && maze[x + 1][y] != 1) {
stack.push(new Node(x + 1, y));
maze[x + 1][y] = 1;
return ;
}
if (y < m - 1 && maze[x][y + 1] != 1) {
stack.push(new Node(x, y + 1));
maze[x][y + 1] = 1;
return ;
}
if (x > 0 && maze[x - 1][y] != 1) {
stack.push(new Node(x - 1, y));
maze[x - 1][y] = 1;
return ;
}
if (y > 0 && maze[x][y - 1] != 1) {
stack.push(new Node(x, y - 1));
maze[x][y - 1] = 1;
return ;
}
//不能往下走 回滚
Node no = (Node)stack.pop();
// maze[no.x][no.y] = 1;
}
}
class Node {
public int x;
public int y;
public Node(int x, int y) {
this.x = x;
this.y = y;
}
}
从单向链表中删除指定值的节点
思路 : 因为链表中不能存在val相同的节点,所以插入 p,e 。就看前置节点p是否存在,p存在那就是在后插新节点e。如果p未遍历到,e已经遍历到了,那就是在e节点前插入新的节点p。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main{
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
String [] ss = line.split(" ");
int n = Integer.parseInt(ss[0]);
int h = Integer.parseInt(ss[1]);
Node head = new Node(h);
for(int i=0;i<2*(n-1);i+=2){
int p = Integer.parseInt(ss[i+2]);
int t = Integer.parseInt(ss[i+3]);
// System.out.println(p+" "+ t);
head = add(head,t,p);
// print(head);
}
int r = Integer.parseInt(ss[ss.length-1]);
head = remove(head,r);
print(head);
}
static Node remove(Node head,int x){
Node pre = null;
Node tem = head;
while(tem!=null){
if(tem.val == x){
if(pre==null) return head.next;
pre.next = tem.next;
return head;
}
pre = tem;
tem = tem.next;
}
return head;
}
// t前置节点 插入在后置节点s之前
static Node add(Node head,int t,int s){
Node pre = null;
Node tem = head;
while(tem!=null){
//后置节点s有值了 说明t没有需要新建
if(tem.val == s){
Node te = new Node(t);
te.next = tem;
if(pre==null){
return te;
}
pre.next = te;
return head;
}
// 前置节点t有值了 说明后置节点s没有
if(tem.val==t){
Node ss = new Node(s);
ss.next = tem.next;
tem.next = ss;
return head;
}
pre = tem;
tem = tem.next;
}
return head;
}
static void print(Node head){
while(head!=null){
System.out.print(head.val+" ");
head = head.next;
}
System.out.println();
}
}
class Node{
int val;
Node next;
public Node(int x){
val = x;
}
}
四则运算
双栈记录操作符和操作数
-
运算符优先级* / 高于+ -
-
数字入栈
-
左括号入栈,留匹配有括号
-
遇到右扩号就对()中进行计算,要求提前处理括号中表达式,对括号中的计算结果只有(10)或者(12+12)或者(1+2*3)好处理,如(1-2+3)不好处理,这就要求第五步。
-
遇到运算符,那就运算符
-
如果是如(- 或者是表达式第一个字符,那就添加数0,用于计算 0 - 4 = -4
-
否则就是正常表达式要求 当前的运算符优先级高于or 等于操作符栈顶的优先级。
形如 1-2+3,遇到+ ,那么-可以提前运算。遇到1+2*3-4 遇到-才计算*以及+。
-
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
import java.util.HashMap;
// import java.util.System;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
String ss = line.replaceAll("\\[", "(").replaceAll("\\]", ")").replaceAll("\\{",
"(")
.replaceAll("\\}", ")");
char chs [] = ss.toCharArray();
//System.out.println(chs);
HashMap<Character, Integer> map = new HashMap<>();
map.put('+', 1);
map.put('-', 1);
// map.put('(', -1);
map.put('*', 3);
map.put('/', 3);
Stack<Double> nums = new Stack<>();
Stack<Character> ops = new Stack<>();
for (int i = 0; i < chs.length; i++) {
if (chs[i] == '(') ops.push(chs[i]);
//数字
else if (Character.isDigit(chs[i])) {
double num = 0.0;
while (i < chs.length && Character.isDigit(chs[i])) {
num = num * 10.0 + (chs[i] - '0');
i++;
}
// System.out.println(num);
nums.push(num);
i--;
} else if (chs[i] == ')') {
// System.out.println(chs[i]);
//遇到 ) 直到遇到 ( 计算括号中的结果
while (!ops.isEmpty() && ops.peek() != '(') {
char c = ops.pop();
double x = nums.pop();
double y = nums.pop();
// System.out.println(y + "" + c + "" + x);
nums.push(cal(y, x, c));
}
if (!ops.isEmpty()) ops.pop();
//运算符
} else {
//说明遇到负数 第一个字符 或者前一个字符是 (
if ((i == 0 || chs[i - 1] == '(') && (chs[i] == '+' || chs[i] == '-')) {
nums.push(0.0);
}
// ops.push(chs[i]);
//当前符号优先级 高于 栈顶就运算
while (!ops.isEmpty() && ops.peek() != '('&&
map.get(ops.peek()) >= map.get(chs[i])) {
char c = ops.pop();
double x = nums.pop();
double y = nums.pop();
// System.out.println(y + "" + c + "" + x);
nums.push(cal(y, x, c));
}
ops.push(chs[i]);
}
}
while (!ops.isEmpty()) {
char c = ops.pop();
double x = nums.pop();
double y = nums.pop();
nums.push(cal(y, x, c));
// System.out.println(y + "" + c + "" + x);
}
System.out.printf("%.0f", nums.peek());
}
static double cal(double a, double b, char op) {
switch (op) {
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
return a / b;
default:
return 0.0;
}
}
}
编辑距离
初始化dp[0][0]表示的是字符串a和b的空字符串编辑距离为0,dp[0][j] = j;这时为了更好的比较像 a , cdfsa这样的情况。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
// import java.lang.Math;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String A = br.readLine();
String B = br.readLine();
char [] a = A.toCharArray();
char [] b= B.toCharArray();
int dp [][] = new int[a.length+1][b.length+1];
for(int i=0;i<=a.length;i++)
Arrays.fill(dp[i],Math.max(a.length,b.length));
dp[0][0] = 0;
for(int i=0;i<=a.length;i++){
dp[i][0] = i;
}
for(int i=0;i<=b.length;i++){
dp[0][i] = i;
}
for(int i=1;i<=a.length;i++){
for(int j=1;j<=b.length;j++){
if(a[i-1]==b[j-1]) {
dp[i][j] = Math.min(dp[i-1][j-1],dp[i][j]);
//b 插入一个字符
// if(i>=2) dp[i][j] = Math.min(dp[i-2][j-1]+1,dp[i][j]);
// //a 插入一个字符
// if(j>=2) dp[i][j] = Math.min(dp[i-1][j-2]+1,dp[i][j]);
}
else {
//不等 删除一个 和插入类似
dp[i][j] = Math.min(dp[i-1][j]+1,dp[i][j]);
dp[i][j] = Math.min(dp[i][j-1]+1,dp[i][j]);
// 替换 或者 插入
// 如 abcd acd b与c比较 往ac之间插入b
dp[i][j] = Math.min(dp[i-1][j-1]+1,dp[i][j]);
}
//System.out.println(i+" "+j+" "+dp[i][j]);
}
}
System.out.println(dp[a.length][b.length]);
}
}
入栈出栈序列问题
计数
Cnm = Cnm-1 + Cn-1m-1
给定入栈序列,判断能否得到指定的出战序列
链接
- 通过辅助栈A判断,对入栈序列每个元素入栈,若A栈顶元素不等于出栈序列元素B,就入栈,直到A栈顶元素等于B就出栈,同时遍历下一个出战序列元素B1,再次判断A栈顶元素是否和B1相等,不同继续入栈,相等出栈,最后栈A为空就是可以,否则不可以。
class Solution {
public boolean validateStackSequences(int[] pushed, int[] popped) {
Stack<Integer> stack = new Stack<>();
int i = 0;
for(int num : pushed) {
stack.push(num); // num 入栈
while(!stack.isEmpty() && stack.peek() == popped[i]) { // 循环判断与出栈
stack.pop();
i++;
}
}
return stack.isEmpty();
}
}
给定入栈序列,求出所有的出战序列
#include <iostream>
#include <stack>
#include <vector>
#include <algorithm>
using namespace std;
// input: 输入序列,i 表示输入到第 i 个,N 表示有 N 个输入元素; seq: 某一个输出序列; result : 存储所有的序列
void GetAllSequence(const int* input, int i, const int N, stack<int> &stk, vector<int> &seq,vector<vector<int> > &result) {
if (i == N) {
// 输入序列全部入栈完毕,只能出栈。将栈中的元素添加到seq 的后面, 保存 seq
if (!stk.empty()) {
int top = stk.top();
seq.push_back(top);
stk.pop();
GetAllSequence(input, i, N, stk, seq, result); // 保持 i == N,递归地将 stk 元素复制到 seq
stk.push(top); //回溯
seq.pop_back();
} else {
result.push_back(seq); // 保存结果
}
} else {
// 对于一个输入元素,可以入栈;可以不入,弹出栈中已有元素
// 入栈
stk.push(input[i]);
GetAllSequence(input, i+1, N, stk, seq, result); // 向 i+1 递归
stk.pop(); // 回溯,恢复栈之前的状态
// 出栈
if (!stk.empty()) {
int top = stk.top(); //记录
stk.pop();
seq.push_back(top);
GetAllSequence(input, i, N, stk, seq, result); // 保持 i 不变
seq.pop_back(); // 回溯,恢复栈和序列之前的状态
stk.push(top);
}
}
}
int main()
{
int input[] = {1,2,3}; // 输入序列
const int N = sizeof(input)/sizeof(input[0]);
vector<vector<int> > result; //保存所有序列
vector<int> seq;
stack<int> stk;
GetAllSequence(input, 0, N, stk, seq, result);
for (int i = 0; i < result.size(); i++) {
for (int j = 0; j < result[0].size(); j++) {
cout << result[i][j] << " ";
}
cout << endl;
}
}
真分数分解
如 2/4 分解为 1/3+1/6;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while (br.ready()) {
String str = br.readLine();
// long a[] = Arrays.stream(str.split("/")).mapToLong(Long::parseLong).toArray();
String ss[] = str.split("/");
long a[] = new long[2];
a[0] = Long.parseLong(ss[0]);
a[1] = Long.parseLong(ss[1]);
StringBuilder sb = new StringBuilder();
// System.out.println(a[0]+" "+a[1]);
// if (a[0] == 1) {
// sb.append("1/" + a[1]);
// }
// System.out.println(1%0);
boolean first = true;
while (true) {
if (a[0] == 1) {
if (first) {
sb.append("1/" + a[1]);
first = false;
} else sb.append("+" + "1/" + a[1]);
break;
} else {
long x = a[1] / a[0] + 1;
// System.out.println(x);
if (first) {
sb.append("1/" + x);
first = false;
} else sb.append("+" + "1/" + x);
long z = a[0] * x - a[1];
long m = x * a[1];
long g = gcd(m, z);
z /= g;
m /= g;
a[0] = z;
a[1] = m;
}
}
System.out.println(sb.toString());
}
}
static long gcd(long a, long b) {
while ((a % b) != 0) {
//System.out.println(a + " " + b);
long t = b;
b = a % b;
a = t;
}
return b;
}
}
优化 long x = a[1] / a[0] + 1计算时候,出现除得尽的就相当于是分子和分母能化成分子为1的情况,那么这就是最后一个真分数,直接退出即可。省去gcd部分。
// 有一说一,他们说这是数学家提出的算法,但是我自己也想出来了这个算法,巨开心哈哈哈
import java.io.*;
public class Main{
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str;
while((str = br.readLine())!=null) {
String[] ss = str.split("/");
long a = Integer.parseInt(ss[0]);
long b = Integer.parseInt(ss[1]);
long t;
StringBuilder sb = new StringBuilder();
while(a != 0) {
t = b/a + (b%a==0?0:1);
if (b % t == 0 && a >= t) {
a -= b/t;
sb.append('1').append('/').append(t).append('+');
} else {
a = a * t - b;
b = b * t; // 这里可能溢出,所以都用long
if(a!=0)sb.append('1').append('/').append(t).append('+');
else sb.append('1').append('/').append(t);
}
if(a == 1) {
sb.append('1').append('/').append(b);
break;
}
}
System.out.println(sb);
}
}
}
最长上升子序列长度
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.LinkedList;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String str = br.readLine();
int n = Integer.parseInt(str);
String z[] = br.readLine().split(" ");
if (n <= 1) {
System.out.println(0);
return ;
}
int arr[] = new int [z.length];
int [] B = new int[z.length];
int i = 0;
for (String e : z) {
arr[i++] = Integer.parseInt(e);
}
int max = -1;
for ( i = 0; i < n; i++) {
if (max == -1) {
B[++max] = arr[i];
} else {
if (arr[i] > B[max]) {
B[++max] = arr[i];
} else if (arr[i] < B[max]) {
int index = qs(B, max, arr[i]);
B[index] = arr[i];
}
}
// for(int j=0;j<=max;j++){
// System.out.print(B[j]+" ");
// }
// System.out.println();
}
System.out.println(max + 1);
}
//在B中找大于等于指定数值t的 下标
static int qs(int b[], int s, int t) {
int l = 0, r = s;
while (l < r) {
int mid = (l + r) >> 1;
if (b[mid] >= t) {
r = mid;
} else {
l = mid + 1;
}
}
// System.out.println(l);
return l;
}
}
举证估算量
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.HashMap;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
HashMap<Character, Mutrix> map = new HashMap<>();
int i = 0, sum = 0;
while (n > 0) {
String [] str = br.readLine().split(" ");
map.put((char)('A' + i), new Mutrix(Integer.parseInt(str[0]),
Integer.parseInt(str[1])));
// System.out.println((char)('A'+i));
i++;
n--;
}
Stack<Character> stack = new Stack<>();
char [] chs = br.readLine().toCharArray();
stack.push(chs[0]);
int index = 1;
while (!stack.isEmpty() && i < chs.length) {
if (chs[index] != ')') stack.push(chs[index]);
else {
char tem[] = new char[2];
int j = 0;
while (!stack.isEmpty() && stack.peek() != '(') {
tem[j++] = stack.pop();
}
if (stack.peek() == '(') stack.pop();
// System.out.println(tem[1] + " " + tem[0]);
// sum += cal(tem[1], tem[0], map);
Mutrix m1 = map.get(tem[1]);
Mutrix m2 = map.get(tem[0]);
sum+= m1.r*m1.l*m2.l;
//栈空 计算结束
if(stack.isEmpty()) break;
map.put(tem[1], new Mutrix(m1.r, m2.l));
stack.push(tem[1]);
}
index++;
}
System.out.println(sum);
}
// static int cal(char a, char b, int i, HashMap<Character, Mutrix> map) {
// return m1.r * m1.l * m2.l;
// }
}
class Mutrix {
public int r;
public int l;
public Mutrix(int r, int l) {
this.r = r;
this.l = l;
}
}
求解立方根
泰勒公式:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p0HU20Q2-1690389939898)(https://s2.loli.net/2022/07/13/ujD8NUePKCpVRmE.jpg)]
设f(x) = x3 -A,由泰勒展开 f(x) = x3-A - 3x2 (x-x0)前两项即可,要求f(x)->0时x的值。所以
(x3 -A) /(3x2) = x - x0 ,得到递推计算公式 xn = xn-1 - (x3n-1 -A) /(3x2n-1)。此时代入xn-1,迭代计算xn,直到误差满足要求。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
double d = Double.parseDouble(reader.readLine());
double xa = 1.0, xb = 0.0;
// f(x) - A 计算误差 xn+1 = xn - (xn^3-A)/(3xn^2)
while (true) {
double to = Math.pow(xa, 3.0) - d;
if (Math.abs(to) < 1e-5) break;
xb = xa - to / (3 * Math.pow(xa, 2.0));
xa = xb;
//System.out.println(xa);
}
System.out.printf("%.1f\n",xa);
}
}
递归回溯
24点游戏算法
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String [] number = br.readLine().split(" ");
int[] nums = new int[4]; // 存放数字
boolean[] visit = new boolean[4]; // 存放对应位置数字的使用状态(1代表已使用)
boolean flag = false;
for (int i = 0; i < 4; i++) {
nums[i] = Integer.parseInt(number[i]); // 读取数字
}
int val = 0;
boolean f = dfs(nums, visit, 1, val);
System.out.println(f);
}
//本题对数字选取顺序无要求 全排列
static boolean dfs(int a[], boolean visit[], int nums, int val) {
if (nums == 5 && val == 24) {
return true;
}
if (nums == 5) return false;
boolean flag = false;
for (int i = 0; i < a.length; i++) {
if (!visit[i]) {
visit[i] = true;
//首次递归放入 val = 0
flag |= dfs(a, visit, nums + 1, val + a[i]);
flag |= dfs(a, visit, nums + 1, val - a[i]);
flag |= dfs(a, visit, nums + 1, val * a[i]);
if (val % a[i] == 0) flag |= dfs(a, visit, nums + 1, val / a[i]);
visit[i] = false;
if (flag) return true;
}
}
return false;
}
}
给定入栈序列求出战序列
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
import java.util.LinkedList;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
LinkedList<Integer> in = new LinkedList<>();
LinkedList<String> res = new LinkedList<>();
int n = sc.nextInt();
int arr[] = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
dfs(arr, in, res, "", 0, 0);
Collections.sort(res);
for (String r : res) {
System.out.println(r);
}
}
//in入栈次数 out出栈次数
static void dfs(int []a, LinkedList<Integer> s, LinkedList<String> res,
String str, int in, int out) {
//火车全部出栈了就 退出
if (out == a.length) {
res.add(str);
}
//如果当前栈内不为空 那就出栈
if (!s.isEmpty()) {
int temp = s.pop();
dfs(a, s, res, str + temp + " ", in, out + 1);
//恢复现场 当前火车恢复 看还有未入栈的火车没有
s.push(temp);
}
//如果还有火车未入栈 那就入栈,没有就退出当前层
if (in < a.length) {
s.push(a[in]);
dfs(a, s, res, str, in + 1, out);
//恢复
s.pop();
}
}
}