算法之穷竭搜索

6 篇文章 0 订阅

这两天一直在刷PAT的程序设计题,在基础题中出现最多的就是HASH和穷竭 搜索了 。今天先来整理下穷竭搜索吧。


穷竭搜索是将所有的可能性罗列出来,在其中找到答案的方法,我们也称为暴力法或者蛮力法,有时候对算法的时间和空间要求不高时,可以使用这个办法将所有的结果枚举出来,在结果集中寻找到我们想要的答案。


一般我们通过DFS或者BFS进行实现,也可以直接使用迭代枚举出结果,直接上例子。

/*
	Given a string S, find the longest palindromic substring in S.
	You may assume that the maximum length of S is 1000,
	and there exists one unique longest palindromic substring.
	
	Example
	Given the string = "abcdzdcab", return "cdzdc".
	Challenge
	O(n2) time is acceptable. Can you do it in O(n) time.
	
            大概意思是求最长的回文子串
 */

/*
 * 解法:
 * 		使用穷竭搜索,用一个变量记录最长的回文子串
 * 		找到更长的子串后更新
 */
public class Main3 {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		String line = scan.nextLine();
		// 最长回文子串长度
		int longest = 0;
		// 左边索引
		int left = 0;
		// 右边索引
		int right = 0;
		for (int i = 0; i < line.length(); i++) {
			for (int j = i + 1; j < line.length() + 1; j++) {
				String subStr = line.substring(i, j);
				if (isPalinDromic(subStr) && j - i > longest) {
					longest = j - i;
					left = i;
					right = j;
				}
			}
		}
		String longestSub = line.substring(left, right);
		System.out.println(longestSub);
		scan.close();
	}

	public static boolean isPalinDromic(String str) {
		if (str.isEmpty())
			return false;
		for (int i = 0; i < str.length(); i++) {
			if (str.charAt(i) != str.charAt(str.length() - 1 - i))
				return false;
		}
		return true;
	}
}

这道题通过两层for循环枚举出所有的回文子串,在通过longest变量跟踪得到最长的 回文字符串。



再来一个DFS

/*
	Implement wildcard pattern matching with support for '?' and '*'.
	
	'?' Matches any single character.
	'*' Matches any sequence of characters (including the empty sequence).
	The matching should cover the entire input string (not partial).
	
	Example
	isMatch("aa","a") → false
	isMatch("aa","aa") → true
	isMatch("aaa","aa") → false
	isMatch("aa", "*") → true
	isMatch("aa", "a*") → true
	isMatch("ab", "?*") → true
	isMatch("aab", "c*a*b") → false
	
	类似于实现正则匹配
 */

/*
 *  解法:
 *  使用DFS实现字符串匹配
 */
public class Main4 {
	public static void main(String[] args) {
//		Scanner scan = new Scanner(System.in);
//		String line = scan.nextLine();
		System.out.println(isMatch("aab", "*ba"));
//		scan.close();
	}

	private static boolean isMatch(String s, String p) {
		if (s.isEmpty() || p.isEmpty())
			return false;
		int si = 0;
		int pj = 0;
		return helper(s, si, p, pj);
	}

	private static boolean helper(String s, int si, String p, int pj) {
		if (si == s.length() || pj == p.length()) {
			if (si == s.length() && pj == p.length()) {
				return true;
			} else {
				return false;
			}
		}
		if (p.charAt(pj) == '*') {
			while (p.charAt(pj) == '*') {
				pj++;
				if (pj == p.length())
					return true;
			}
			// 对si进行递推
			while (si < s.length() && !helper(s, si, p, pj)) {
				si++;
			}
			// 如果不是子串的话,返回true
			return si != s.length();
		} else if (s.charAt(si) == p.charAt(pj) || p.charAt(pj) == '?') {
			return helper(s, si + 1, p, pj + 1);
		} else {
			return false;
		}
	}
}
这道题类似于正则表达式的匹配问题,难点在于找到‘’*‘时的匹配字符,在找到‘*’时,必须逐渐对原字符串进行递推,知道找到下一个跟模式匹配的字符,这就是DFS的基本思路。


最后一个,经典的部分和问题

/*
 * 部分和问题
 * 
 * 给定整数a1,a2,...,an,判断是否可以从中选出若干数,使他们的和恰好为k
 * 
 * Example input : 
 *             n = 4
 *             a = {1,2,4,7}
 *             k = 13
 *         output : 
 *         	   Yes {13 = 2+4+7}
 *         
 *         
 * 解法思路:使用穷竭搜索(DFS)从一个状态开始,直到状态无法转移
 *         此时会找到 所有的解,从此解 中寻找答案
 */
public class Main {
	private static int[] A;
	private static int N, K;

	public static void main(String[] args) {

		// input
		Scanner scan = new Scanner(System.in);
		N = scan.nextInt();
		A = new int[N];
		for (int i = 0; i < N; i++) {
			A[i] = scan.nextInt();
		}
		K = scan.nextInt();
		scan.close();
		// slove and output
		System.out.println(DFS(0,0));
	}

	/**
	 * 深度搜索所有可行的结果
	 * 已经从前n项得到了sum,对第n项之后的元素进行分支
	 */
	private static boolean DFS(int n, int sum) {
		if(n == N ) return sum == K;
		// 加上下一个元素的情况
		if(DFS(n+1,sum+A[n])) return true;
		// 不加下一个元素的情况
		if(DFS(n+1,sum)) return true;
		// 如果都没有返回,即无法等于K
		return false;
	}

}
DFS时会自动进行进行状态转移,我们需要对状态转移的过程了如执掌,这样才能掌握这种思想。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 MATLAB 中处理表格的一种常用方是使用表格(table)数据类型。使用 table 数据类型可以方便地导入、处理和分析表格数据。在本问题中,您可以使用 table 数据类型来加载包含测量的形态学和鳞序特征的数据。首先,您需要将数据文件导入到 MATLAB 中。您可以使用以下代码将 CSV 文件加载到 table 中: ```matlab data = readtable('filename.csv'); ``` 接下来,您可以使用以下代码来选择包含测量的形态学和鳞序特征的列: ```matlab X = data(:, {'feature1', 'feature2'}); ``` 其中,'feature1' 和 'feature2' 分别是包含您要使用的测量特征的列的名称。接下来,您可以将第 5 种蜥蜴与所有其他蜥蜴区分开来。您可以使用以下代码将数据分成两个集合: ```matlab idx = (data.species == 5); X_species5 = X(idx, :); X_other_species = X(~idx, :); ``` 其中,'species' 是包含蜥蜴种类的列的名称。现在,您可以使用测量的形态学和鳞序特征中的两个变量来找到最佳的“预测变量对”。您可以使用以下代码来进行穷尽搜索: ```matlab best_corr = 0; for i = 1:size(X, 2) for j = (i+1):size(X, 2) corr = corrcoef(X_species5{:, i}, X_species5{:, j}, 'Rows', 'complete'); if corr(1, 2) > best_corr best_corr = corr(1, 2); best_vars = {X.Properties.VariableNames{i}, X.Properties.VariableNames{j}}; end end end ``` 其中,'corrcoef' 函数用于计算两个变量之间的相关系数。'Rows' 参数指定计算相关系数时应排除缺失值。通过穷尽搜索,您可以找到最佳的“预测变量对”,并使用这些变量来区分第 5 种蜥蜴与其他蜥蜴。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值