js实现几个算法题

题目:字符串消除

给定一个字符串,仅由a,b,c 3种小写字母组成。当出现连续两个不同的字母时,你可以用另外一个字母替换它,如 有ab或ba连续出现,你把它们替换为字母c; 有ac或ca连续出现时,你可以把它们替换为字母b; 有bc或cb 连续出现时,你可以把它们替换为字母a。 你可以不断反复按照这个规则进行替换,你的目标是使得最终结果所得到的字符串尽可能短,求最终结果的最短长度。 输入:字符串。长度不超过200,仅由abc三种小写字母组成。 输出: 按照上述规则不断消除替换,所得到的字符串最短的长度。 例如:输入cab,输出2。因为我们可以把它变为bb或者变为cc。           输入bcab,输出1。尽管我们可以把它变为aab -> ac -> b,也可以把它变为bbb,但因为前者长度更短,所以输出1。

解答:
这个题目的实现是比较有难度的,要善于发现规律才能够正确解答。没有参考网络答案的情况下我自己思考了一下,主要是实现思路。同样,我的答案不一定是最优的,如有更好的解法可以留言,向众定感激涕零!下面给出我的实现代码。是的,可能你已经意料到了,依旧是js实现。。里面用了递归实现,大家自行参考。

function getRes(str){
if(/^([a-cA-C])\1*$/g.test(str)){
return str;
}
var allRepAry = getAllRep(str),
index,strLen,subLen;
if(allRepAry){ //有重复
var v=allRepAry[0];
index = str.indexOf(v);
strLen = str.length;
subLen = v.length;
var compStr; 
if(index === 0){ // 开头
compStr = v+str.charAt(subLen);
}else{// 结尾或中间
compStr = str.charAt(index-1)+v;
}
str = str.replace(compStr,removeRep(compStr,v));
str = getRes(str);

}else{ //没有重复的
var firTwoStr = str.substring(0,2);
str = str.replace(firTwoStr,dif(firTwoStr));
str = getRes(str);
}
return str;
}

function removeRep(str,rep){
var isOdd = rep.length%2 === 0,
index = str.indexOf(rep),
repLen = rep.length,
oneS = rep.charAt(0),
secS = index === 0?str.slice(repLen,repLen+1):str.slice(0,1);

if(isOdd){
return secS;
}else{
var sss = "abc",
ind1 = sss.indexOf(oneS),
ind2 = sss.indexOf(secS);
return sss.charAt(3-ind1-ind2);
}
}
function dif(str){
if(!/^[a-cA-C]{2}$/g.test(str)){
throw new Error("请输入长度为2且只包含a、b、c的字符串");
}
var s = "abc",
s1 = str.charAt(0),
s2 = str.charAt(1),
ind1 = s.indexOf(s1),
ind2 = s.indexOf(s2);
return /^([A-Za-z])\1$/g.test(str)?str:s.charAt(3-ind1-ind2);
}
function getAllRep(str){
return str.match(/([a-cA-C])\1+/g);// 要求至少有两个重复
}
function getManLen(str){
return getRes(str).length;
}
	console.log(getManLen("bcab")); 

题目:数组排序
给定一个包含1-n的数列,我们通过交换任意两个元素给数列重新排序。求最少需要多少次交换,能把数组排成按1-n递增的顺序,其中,数组长度不超过100。 例如: 原数组是3,2,1, 我们只需要交换1和3就行了,交换次数为1,所以输出1。 原数组是2,3,1,我们需要交换2和1,变成1,3,2,再交换3和2,变为1,2,3,总共需要的交换次数为2,所以输出2。  
解答: 
我这里给出我自己的解答,可能不是最优,大家如果有更好的解法可以给我留言,我再添加上。还是老样,暂只用js给出解答,仅供参考。所有代码都已经测试过,能正常运行。大体思路:注意题目中的数据列表是从1到n,则在数组里每个位置i对应的值为i+1。找出数列中最大的不在自己正确位置上的数,然后和最右边的不在自己正确位置上的数进行交换,重复此过程直到排序结束。只要能想到,思路还是比较简单的。 

function sort(ary){
	if(!~getMax(ary)){
		return 0;
	}
	var len = ary.length,
		change = 0,
		j;
	for(var i =0;i<len;i++){
		j = i+1;
		if(ary[i] !== j){
			ary = ary.slice(i);
			break;
		}
	}
	for(var i =len;i>=0;i--){
		j = i+1;
		if(ary[i] !== j){
			ary = ary.slice(0,i);
			break;
		}
	}
	console.log(ary);
	var maxWroInd,maxRig;
	while(~(maxWroInd=getMax(ary))){
		maxRig = getRight(ary,maxWroInd);
		ary[maxWroInd] = [ary[maxRig],ary[maxRig] = ary[maxWroInd]][0];
		change++;
	}
	return change;
} 
function getMax(ary){
	var len =  ary.length,
		i = 0,
		maxNum = -Infinity,
		index = -1,
		j,curNum,afterNum;
	for(;i<len;i++){
		curNum = ary[i];
		for(j = i+1;j<len;j++){
			afterNum = ary[j];
			if(curNum > afterNum && maxNum < curNum){
				maxNum = curNum;
				index = i;
			}
		}
	}
	return index;
}

function getRight(ary,index){
	var maxWro = ary[index];
	var len = ary.length,
		i = len;
	for(;i>=0;i--){
		if(ary[i] < maxWro){
			return i;
		}
	}
}

console.log(sort([3,1,5,2,4])); // 4 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
贪心算法是一种简单且常用的算法思想,在解决一些优化问时非常高效。下面是几个经典的使用贪心算法的例子: 1. 找零钱问:假设有一定面额的硬币,如1元、5元、10元、20元等,并且数量无限。现在要找给客户m元的零钱,如何使用最少的硬币数量?贪心算法的思想是从面额最大的硬币开始尽可能多地使用。 2. 区间调度问:给出一组区间,求解最多能够选择多少个互不重叠的区间。贪心算法的思想是按照区间的结束时间排序,然后依次选择结束时间最早的区间。 3. 最小生成树问:给出一个无向图,边带有权值,求解一个最小生成树,即含有所有顶点的连通子图并且权值和最小。贪心算法的思想是从一个任意顶点开始,每次选择一条权值最小的边,并且要保证不构成回路。 4. 背包问:给出一组物品,每个物品有自己的价值和重量,并且背包只能承受一定的重量。现在要选择一些物品放入背包中,使得总价值最大。贪心算法的思想是按照物品的单位价值(价值/重量)排序,然后依次选择单位价值最高的物品放入背包。 以上是几个常见的使用贪心算法的经典例子。贪心算法虽然简单,但并不一定能够得到全局最优解,它只能得到局部的最优解。因此,在使用贪心算法时需要注意验证其正确性,并且多结合其他算法思想进行优化。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值