Recursion 计算表达式的括号组合 @CareerCup

表达式计算(C++ STL 实现) 通过逆波兰式来计算数学中的中缀表达式,例如:3+(4-7*5),主要是处理运算优先级问题。源码里面的注释非常详细,由于基于基本数据类型实现,实用价值较小,用作学习还是很不错的。(支持的符号(半角模式):0123456789 ( ) .(小数点) + - * / !(阶乘) ^(次方)) 立即下载

还没细看,先把代码放在这里


package Recursion;

import java.util.HashMap;

/**
 * Given a boolean expression consisting of the symbols 0,1, &, /, and ^ , and a
 * desired boolean result value result, implement a function to count the number
 * of ways of parenthesizing the expression such that it evaluates to result.
 * 
 * 给出一个包含0,1, &, /, ^符号的表达式,和一个预期结果。实现一个方法来计算有多少种括号
 * 的组合能使得表达式的结果和预期结果一样。
 */
public class S9_11 {

	public enum Term {
		True, False, And, Or, Xor, LeftParen, RightParen
	};

	public static String reduce(String expression, int start, int end) {
		if (start == end) {
			if (expression.charAt(start) == '1') {
				return "1";
			} else if (expression.charAt(start) == '0') {
				return "0";
			}
		}
		int count = 0;
		int i = 0;
		String[] reduced = new String[3];
		int index = 0;
		int left = start;
		int right = start;
		for (i = start; i <= end; i++) {
			if (expression.charAt(i) == '(') {
				if (count == 0) {
					left = i + 1;
				}
				count++;
			} else if (expression.charAt(i) == ')') {
				count--;
				if (count == 0) {
					right = i - 1;
				}
			}
			if (count == 0) {
				reduced[index] = reduce(expression, left, right);
				if (index == 0) {
					reduced[index + 1] = Character.toString(expression
							.charAt(i + 1));
					i += 1;
					left = i + 1;
					right = i + 1;
				}
				index += 2;
			}
		}
		if (reduced[1].equals("&")) {
			if (reduced[0].equals("1") && reduced[2].equals("1")) {
				return "1";
			}
			return "0";
		} else if (reduced[1].equals("|")) {
			if (reduced[0].equals("1") || reduced[2].equals("1")) {
				return "1";
			}
			return "0";
		} else if (reduced[1].equals("^")) {
			if (reduced[0].equals("1") && reduced[2].equals("0")) {
				return "1";
			} else if (reduced[0].equals("0") && reduced[2].equals("1")) {
				return "1";
			}
			return "0";
		}
		return "0";
	}

	public static boolean evaluate(String expression, int start, int end) {
		String result = reduce(expression, start, end);
		if (result == "0") {
			return false;
		} else {
			return true;
		}
	}

	public static boolean isOperator(char c) {
		switch (c) {
		case '&':
		case '|':
		case '^':
			return true;
		default:
			return false;
		}
	}

	public static String insertParensAround(String expression, int ind) {
		int left = 0;
		int right = 0;
		int index = 0;
		int count = 0;
		for (int i = 0; i < expression.length(); i++) {
			if (isOperator(expression.charAt(i))) {
				if (count == ind) {
					index = i;
				}
				count++;
			}
		}
		count = 0;
		for (int i = index - 1; i >= 0; i--) {
			if (expression.charAt(i) == ')') {
				count++;
			} else if (expression.charAt(i) == '(') {
				count--;
			}
			if (count == 0) {
				left = i;
				break;
			}
		}
		count = 0;
		for (int i = index + 1; i <= expression.length(); i++) {
			if (expression.charAt(i) == '(') {
				count++;
			} else if (expression.charAt(i) == ')') {
				count--;
			}
			if (count == 0) {
				right = i;
				break;
			}
		}
		if (left == 0 && right == expression.length() - 1) {
			return expression;
		}
		String newexpression = expression.substring(0, left) + '('
				+ expression.substring(left, right + 1) + ')'
				+ expression.substring(right + 1);
		return newexpression;
	}

	public static int bruteForce(String expression,
			HashMap<String, Boolean> completed, boolean result, boolean[] flags) {
		int count = 0;
		boolean isDone = true;
		if (completed.containsKey(expression)) {
			return 0;
		}

		for (int i = 0; i < flags.length; i++) {
			if (!flags[i]) {
				flags[i] = true;
				String newexpression = insertParensAround(expression, i);
				isDone = false;
				count += bruteForce(newexpression, completed, result, flags);
				flags[i] = false;
			}
		}

		if (isDone) {
			if (evaluate(expression, 0, expression.length() - 1) == result) {
				System.out.println(expression + " = " + result);
				return 1;
			} else {
				System.out.println(expression + " = " + !result);
				return 0;
			}
		}
		completed.put(expression, true);
		return count;
	}

	public static int countR(String exp, boolean result, int start, int end) {
		if (start == end) {
			if (exp.charAt(start) == '1' && result) {
				return 1;
			} else if (exp.charAt(start) == '0' && !result) {
				return 1;
			}
			return 0;
		}
		int c = 0;
		if (result) {
			for (int i = start + 1; i <= end; i += 2) {
				char op = exp.charAt(i);
				if (op == '&') {
					c += countR(exp, true, start, i - 1)
							* countR(exp, true, i + 1, end);
				} else if (op == '|') {
					c += countR(exp, true, start, i - 1)
							* countR(exp, false, i + 1, end);
					c += countR(exp, false, start, i - 1)
							* countR(exp, true, i + 1, end);
					c += countR(exp, true, start, i - 1)
							* countR(exp, true, i + 1, end);
				} else if (op == '^') {
					c += countR(exp, true, start, i - 1)
							* countR(exp, false, i + 1, end);
					c += countR(exp, false, start, i - 1)
							* countR(exp, true, i + 1, end);
				}
			}
		} else {
			for (int i = start + 1; i <= end; i += 2) {
				char op = exp.charAt(i);
				if (op == '&') {
					c += countR(exp, false, start, i - 1)
							* countR(exp, true, i + 1, end);
					c += countR(exp, true, start, i - 1)
							* countR(exp, false, i + 1, end);
					c += countR(exp, false, start, i - 1)
							* countR(exp, false, i + 1, end);
				} else if (op == '|') {
					c += countR(exp, false, start, i - 1)
							* countR(exp, false, i + 1, end);
				} else if (op == '^') {
					c += countR(exp, true, start, i - 1)
							* countR(exp, true, i + 1, end);
					c += countR(exp, false, start, i - 1)
							* countR(exp, false, i + 1, end);
				}
			}
		}
		return c;
	}

	public static int countDP(String exp, boolean result, int start, int end,
			HashMap<String, Integer> cache) {
		String key = "" + result + start + end;
		if (cache.containsKey(key)) {
			return cache.get(key);
		}
		if (start == end) {
			if (exp.charAt(start) == '1' && result == true) {
				return 1;
			} else if (exp.charAt(start) == '0' && result == false) {
				return 1;
			}
			return 0;
		}
		int count = 0;
		if (result) {
			for (int i = start + 1; i <= end; i += 2) {
				char op = exp.charAt(i);
				if (op == '&') {
					count += countDP(exp, true, start, i - 1, cache)
							* countDP(exp, true, i + 1, end, cache);
				} else if (op == '|') {
					count += countDP(exp, true, start, i - 1, cache)
							* countDP(exp, false, i + 1, end, cache);
					count += countDP(exp, false, start, i - 1, cache)
							* countDP(exp, true, i + 1, end, cache);
					count += countDP(exp, true, start, i - 1, cache)
							* countDP(exp, true, i + 1, end, cache);
				} else if (op == '^') {
					count += countDP(exp, true, start, i - 1, cache)
							* countDP(exp, false, i + 1, end, cache);
					count += countDP(exp, false, start, i - 1, cache)
							* countDP(exp, true, i + 1, end, cache);
				}
			}
		} else {
			for (int i = start + 1; i <= end; i += 2) {
				char op = exp.charAt(i);
				if (op == '&') {
					count += countDP(exp, false, start, i - 1, cache)
							* countDP(exp, true, i + 1, end, cache);
					count += countDP(exp, true, start, i - 1, cache)
							* countDP(exp, false, i + 1, end, cache);
					count += countDP(exp, false, start, i - 1, cache)
							* countDP(exp, false, i + 1, end, cache);
				} else if (op == '|') {
					count += countDP(exp, false, start, i - 1, cache)
							* countDP(exp, false, i + 1, end, cache);
				} else if (op == '^') {
					count += countDP(exp, true, start, i - 1, cache)
							* countDP(exp, true, i + 1, end, cache);
					count += countDP(exp, false, start, i - 1, cache)
							* countDP(exp, false, i + 1, end, cache);
				}
			}
		}
		cache.put(key, count);
		return count;
	}

	public static int total(int n) {
		// Function to return (2n) ! / ((n+1)! * n!)

		// To keep the numbers small, we divide by i when possible to do evenly.
		// If not,
		// we store up the remainder and divide when possible.
		long num = 1;
		long rem = 1;
		for (int i = 2; i <= n; i++) {
			num *= (n + i);
			rem *= i;
			if (num % rem == 0) {
				num /= rem;
				rem = 1;
			}
		}
		return (int) num;
	}

	public static int countDPEff(String exp, boolean result, int start,
			int end, HashMap<String, Integer> cache) {
		String key = "" + start + end;
		int count = 0;
		if (!cache.containsKey(key)) {
			if (start == end) {
				if (exp.charAt(start) == '1') {
					count = 1;
				} else {
					count = 0;
				}
			}

			for (int i = start + 1; i <= end; i += 2) {
				char op = exp.charAt(i);
				if (op == '&') {
					count += countDPEff(exp, true, start, i - 1, cache)
							* countDPEff(exp, true, i + 1, end, cache);
				} else if (op == '|') {
					int left_ops = (i - 1 - start) / 2; // parens on left
					int right_ops = (end - i - 1) / 2; // parens on right
					int total_ways = total(left_ops) * total(right_ops);
					int total_false = countDPEff(exp, false, start, i - 1,
							cache) * countDPEff(exp, false, i + 1, end, cache);
					count += total_ways - total_false;
				} else if (op == '^') {
					count += countDPEff(exp, true, start, i - 1, cache)
							* countDPEff(exp, false, i + 1, end, cache);
					count += countDPEff(exp, false, start, i - 1, cache)
							* countDPEff(exp, true, i + 1, end, cache);
				}
			}
			cache.put(key, count);
		} else {
			count = cache.get(key);
		}
		if (result) {
			return count;
		} else {
			int num_ops = (end - start) / 2;
			return total(num_ops) - count;
		}
	}

	public static void main(String[] args) {
		String terms = "0^0|1&1^1|0|1";
		boolean result = true;

		bruteForce(terms, new HashMap<String, Boolean>(), result,
				new boolean[(terms.length() - 1) / 2]);
		System.out.println(countR(terms, result, 0, terms.length() - 1));
		System.out.println(countDP(terms, result, 0, terms.length() - 1,
				new HashMap<String, Integer>()));
		System.out.println(countDPEff(terms, result, 0, terms.length() - 1,
				new HashMap<String, Integer>()));

	}
}


fibplus-8.0.0.zip FIBPlus 是一套面向 Delphi / C++Builder 的 Firebird、InterBase 数据库访问组件,特点是直接走原生客户端 API,不经 BDE/ODBC,速度快且可控性强。8.0.0 版本主要适配 Delphi 2009 及以后的版本(Delphi 6–2007 需用 7.9.x),核心组件包括 TpFIBDatabase、TpFIBTransaction、TpFIBDataSet 等,支持精细事务管理、本地缓存、BLOB 处理和备份恢复等数据库服务。该库原为 Devrace 的商业组件,现由社区在 GitHub 的 madorin/fibplus 项目开源维护,建议从官方仓库获取源码而非第三方网盘压缩包。安装时解压后用对应版本的工程组(10.4+ 统一为 `FIB.groupproj`)Build 全部包,再 Install `dclFIB` 并在 Library 路径加入 Source 目录即可。新项目中若需官方技术支持,也可考虑 FireDAC、IBDAC 等更现代的替代方案。 立即下载

相关推荐

NE5532A与JRC4580在低噪声音频电路设计中的关键应用

本文深入探讨了经典运算放大器NE5532A与JRC4580在低噪声音频电路设计中的核心应用。文章从噪声模型分析入手,阐述了针对低阻抗信号源时,如何利用这两款BJT输入运放的低电流噪声特性进行优化设计。通过对比两者参数与实战守则,为设计高保真音频前级、耳机放大等电路提供了从原理图到PCB布局的完整低噪声解决方案。

weixin_29295541的博客 328

Java代码配置的表达式解析 之 SpEL表达式

背景: 有些场景下,可能需要把一些java代码的表达式,做成配置化的形式,存储到db中;使用时,从db读取,这时候就需要解析java代码表达式。下面简单介绍通过SpEL 表达式 进行解析。 实际使用: /** * value与配置的表达式匹配 * @param value 值 * @param expressionDefinition 表达式 ...

forBurnInG的专栏 1813

告别安装烦恼!Orange3 3.38.0 Windows绿色版下载即用,附保姆级汉化与组件配置指南

本文详细介绍了Orange3 3.38.0 Windows绿色版的下载与使用,包括中文汉化、组件配置及高效管理技巧。这款无需安装的数据科学工具特别适合快速验证想法的研究人员和移动办公用户,支持多种数据源和可视化工具,大幅提升工作效率。

weixin_30897233的博客 598

Recursion n对括号的组合 @CareerCup

看不太习惯书上写的递归,觉得没有自己写的清晰。 这道题唯一要满足的条件就是在任何时候,左括号数量一定要大等于右括号的数量。 package Recursion; import java.util.HashSet; import java.util.Set; /** *Implement an algorithm to print all valid (e.g., properly

1779

Comsol超声空化气泡仿真:从基础理论到工业应用实践

本文详细介绍了Comsol超声空化气泡仿真的基础理论及工业应用实践。通过解析超声空化现象、Comsol模型搭建流程及求解器优化技巧,帮助工程师掌握气泡仿真技术,提升超声波清洗和乳液制备等工业应用的效率与质量。

weixin_27966471的博客 251

DaVinci Developer中枚举类型变量的创建与实战应用

本文详细介绍了在DaVinci Developer中创建和使用枚举类型变量的方法与实战应用。通过智能温控系统的案例,阐述了枚举类型在嵌入式开发中的核心价值,包括提升代码可读性、类型安全性和维护便捷性。文章还提供了枚举类型在状态机实现和多模块协同中的高级应用技巧,以及调试与优化的实用建议。

ik678901234的博客 511

问题 A: 计算组合数

题目链接:http://codeup.cn/problem.php?cid=100000595&pid=0 题目描述 编制程序,输入m,n(M>=n>=0)后,计算下列表达式的值并输出: m! ———————— n! (m-n)! 要求将计算阶乘运算的函数写为fact(n),函数返回值的类型为float 输入 m n 输出 对应表达式的值 样例输入 2...

Rhao的博客 419

华为OD机试 - 音乐小说内容重复识别 - 并查集(Java 双机位C卷 200分)

华为OD机试 双机位C卷题库疯狂收录中,刷题。

学Java,找哪吒 159

Hard 单词变型成另一个单词 @CareerCup

对起始单词的每一个字母都做替换,把替换后的单词加入到queue中,并同时维护一个Map来记录变化前单词和变化后单词的联系。用来回溯时能打印出路径。 package Hard; import java.util.HashSet; import java.util.LinkedList; import java.util.Map; import java.util.Queue; impor

4761

Spring AI Alibaba实战训练营-16 NL2SQL (自然语言转 SQL)应用开发指南

本文介绍了一个基于AI的智能BI应用开发项目,主要实现自然语言转SQL(NL2SQL)功能,包含对话模块、MCP模块、向量数据管理模块。项目采用Spring AI Alibaba框架,集成通义千问大模型,支持内存向量库和AnalyticDB向量数据库两种存储方案。重点展示了chat模块的三个控制器实现:AnalyticNl2SqlController用于生产环境,SimpleChatController适用于开发测试,Nl2sqlForGraphController支持基于图的复杂对话流程。系统通过将业务知

program哲学 1585

【异常】Codybuddy Error Code: 14003 too many requests 限流报错问题排查与解决指南

14003报错本质为服务端限流拦截,并非账号封禁或程序致命故障,90%以上的场景可通过等待冷却+规范使用行为解决。通过本文的排查步骤,可快速恢复工具使用,同时规避后续重复触发该问题。

奶爸的编程之路,也就一周冷个三天 1253

Hard 找到由其它单词组成的最长单词 @CareerCup

用DFS的那个模板就能做出来,值得注意的是一个词必须被除自己外的其他词组成才行,不能是自己组成自己。 package Hard; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import CtCILibrary.A

3649

白话讲解帕累托前沿点(Pareto Frontier)基础知识与实例解析

排除所有“劣解”,缩小决策范围;量化目标间的“权衡关系”(如“每增加1千元成本,续航提升多少小时”);支持不同场景下的个性化选择,平衡冲突目标。无论是手机选购、汽车设计,还是城市规划,帕累托前沿都是从“混乱的多目标”到“清晰的权衡”的关键桥梁,是现代决策科学中不可或缺的工具。通过数学建模,工程很多问题都可以建模成帕累托前沿求解问题,通过线性规划CPLEX、Gurobi 等优化工具,可以方便进行求解。

2138

Tree_Graph 判断T2是否为T1的子树 @CareerCup

原文: You have two very large binary trees: T1, with millions of nodes, and T2, with hundreds of nodes. Create an algorithm to decide if T2 is a subtree of T1 译文: 有两棵很大的二叉树:T1有上百万个结点,T2有上百个结点。写

3487

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Stack_Queue 把栈排序 Sort a stack @CareerCup

原文: Write a program to sort a stack in ascending order. You should not make any assumptions about how the stack is implemented. The following are the only functions that should be used to write thi

3231

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

Stack_Queue 猫狗队列问题 Cat dog queue @CareerCup

An animal shelter holds only dogs and cats, and operates ona strictly “first in, first out” basis. People must adopt either the “oldest”(based on arrival time) of all animals at the shelter, or they

3092

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Recursion 字符串的全排列 String Permutation @CareerCup

字符串全排列的题目,还是套用模板,同样要注意ret的size问题会变化。而且与上一题不同的是不光是要在ret后面添加进新的组合,而且还要移除前面用过的组合。类似一个队列。 另外Java的substring中区间闭合情况是左闭右开 [ ) 所以想把一个字符串拆成两个区间就可以用这一句: for(int j=0; j<=tmp.length(); j++){ // substring

2977

Moderate 判断井字游戏的胜利 @CareerCup

基于要查找的次数来决定是否要预处理。预处理方式按照3进制来做。 另外,检查是否赢了要判断横行,纵列,正反对角线 package Moderate; /** * Design an algorithm to figure out if someone has won in a game of tic-tac-toe. 译文: 设计算法检查某人是否赢得了井字游戏。 *

2970

LinkLists 检查一个链表是否为回文 Check if a linked list is palindrome @CareerCup

Implement a function to check a linked list is a palindrome 检查一个链表是否为回文 思路: 1 Iterative,利用栈,把链表前半段存入栈,再逐个弹栈和链表后半段比较。注意链表长度为奇数的情况!要跳过中间节点! 2 递归! 定义递归函数为 Result rec(LinkedListNode head, int l

2921

Tree_Graph LCA(Lowest Common Ancestor) 最低公共节点 (BST或者一般树) @CareerCup

原文: Design an algorithm and write code to find the first common ancestor of two nodes in a binary tree. Avoid storing additional nodes in a data structure. NOTE: This is not necessarily a binary se

2627

Sorting_Searching 叠罗汉 @CareerCup

类似前面的一道堆箱子 普适的解法是回溯,注意这类是求最值的回溯题。 另一种解法是LIS,先把其中一维排序,然后对剩下的一维进行LIS package Sorting_Searching; import java.util.ArrayList; import java.util.Collections; /** * A circus is designing a tower r

2461

Hard 随机洗牌函数 @CareerCup

第i个元素和index在[0,i]之间的一个数随机交换 package Hard; import CtCILibrary.AssortedMethods; /** * * Write a method to shuffle a deck of cards. It must be a perfect shuffle - in other words, each 52! permu

2421

Sorting_Searching 读入数字流求rank @CareerCup

用BST实现 package Sorting_Searching; import CtCILibrary.AssortedMethods; /** * Imagine you are reading in a stream of integers. Periodically, you wish to be * able to look up the rank of a n

2383

Moderate rand5()产生rand7() @CareerCup

参考这一文 http://hawstein.com/posts/19.10.html 比书上写得好 package Moderate; /** * * Write a method to generate a random number between 1 and 7, given a method that generates a random number betwe

2367

Recursion 硬币组合问题 @CareerCup

非常有意义的一道题,关键的一点要知道DFS是有顺序的,即在DFS中(5,1)和(1,5)是不一样的组合。所以对这道题我的第一种解法就重复算了多次,具体如图所示:当计算f(10)时,DFS给出的结果是9次,但实际上应该是4. 去重的方法是多用一个变量(level)来限制条件。这样能保证在访问对于给定level只会深搜小于等于level的分支。 同样参考了http://hawstein.c

2366

Hard 大文本找两个单词最短距离 @CareerCup

如果只要找一次就用第一种O(n)解法 如果要找多次就多用一个Hashtable,把所有的组合都保存起来 package Hard; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import CtCILibrary.AssortedMethods; /** * You

2363
上一篇: Recursion 叠箱子最高问题 @CareerCup
下一篇: 如何杀死Chrome进程并重启Chrome
chiiis
博客等级 码龄14年 422粉丝 429原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值