JavaScript的字符串、数组作业讲解

第1题

编写函数repeat(char,n) 实现重复char字符串n次。比如repeat("★",6)返回”★★★★★★”

方法1:
我们现在发现,只需要进行n次的相同操作:每次str末尾增加1颗★
str增加字符,使用连字符,或者用str.concat();

str += “★” 这条语句重复执行n次就可以了。

function repeat(char,n){
    var str = ""
    for(var i = 1 ; i <= n ; i++){
        str = str.concat(char)
    }
    return str;
}

方法2:

二分法

首先我们来看看刚才的算法,有没有什么效率问题?效率低下。

比如我们要制造16颗★,那么我们刚才的算法,要重复执行16次,其实没有必要。

因为★ →★★ → 直接复制自己→★★★★→直接复制自己→★★★★★★★★→16颗星星。

也就是说,我们没有必要一次都增加一颗星星,因为我们已经在第二次循环的时候,得到了★★,那为什么不直接复制自己得到4颗呢??

现在的问题来了,我们的n不一定是2的某次方。比如我们输入16,可以按倍数来。比如用户输入13,怎么办?

其实有办法,因为我们发现,任何数字都能够直接表示为1、2、4、8、16、32、64……的和。

比如:

7 = 4 + 2 + 1;

9 = 8 + 1;

13 = 8 + 4 + 1;

29 = 16 + 8 + 4 + 1;

任何数字都能拆分为1、2、4、8、16、32、64……的和。

所以我们现在就能想到一种算法,就是把这个星星的数量,就在这个数字拆分的那个数值上,进行复制一倍。

比如我们现在要13颗星星,那么1颗(要) → 2颗(不累加) → 4颗(要) → 8颗(要)

伪代码:

循环开始之前,
结果串str   “”
临时串char	“★”
数量n

循环:
如果n是奇数,那么str要加上char;如果n是偶数,str不变。(奇变偶不变)
n = parseInt(n / 2);    //n越除越小
char = char + char;		//每次循环,char都要倍增。
循环直到n1截止。

试着遍历一下repeat(“★”,13)

循环开始之前:
str		 “”
char  	“★”
n   	131次循环:
n此时13是奇数,str就要加上char,所以str变为★
n变为6
char要复制自己一倍,char变为★★

第2次循环:
n此时6是偶数,str不变。str仍为★
n变为3
char要复制自己一倍,char变为★★★★

第3次循环:
n此时3是奇数,str就要加上char,所以str变为★★★★★
n变为1
char要复制自己一倍,★★★★★★★★

第4次循环:
n此时1是奇数,str就要加上char,所以★★★★★★★★★★★★★
n已经是1了,不需要再除了,退出循环,打完收工。

叫做“1248因数法”、“1248拆分法” 把任何一个数字拆成1、2、4、8、16……和。

function repeat(char,n){
	var str = "";
	while(true){
		if(n % 2 == 1){
			//奇变偶不变
			str += char;
		}
		//终点验证
		if(n == 1 || n == 0){
			break;
		}
		//改变n的值
		n = parseInt(n / 2);
		//每次循环,char都要倍增
		char = char + char;
	}
	return str;
}

第2题

在控制台输出图形:

    *
   ***
  *****
 *******
*********

一共5行,比如行号是i,i从1开始,每行的内容: 5-i个空格 和 2i - 1个星星
重复空格5-i次,重复星星2i-1次。

<script type="text/javascript">
	var str1;
	var str2;
	var str;
	for(var i = 1 ; i <= 5 ; i++){
		str1 = repeat(" ",5 - i);
		str2 = repeat("*",2 * i - 1);
		str = str1 + str2;
		console.log(str);
	}
	


	function repeat(char,n){
		var str = "";
		while(true){
			if(n % 2 == 1){
				//奇变偶不变
				str += char;
			}
			//终点验证
			if(n == 1 || n == 0){
				break;
			}
			//改变n的值
			n = parseInt(n / 2);
			//每次循环,char都要倍增
			char = char + char;
		}
		return str;

	}
</script>

第3题

编写函数rev(char) 实现将字符串char倒置,比如rev("spring") 返回”gnirps”

方法1:就是for循环从最后一位开始取源字符串的字符,然后拼接到新的串中。

经典面试题,经典解法。
就是for循环从最后一位开始取源字符串的字符,然后拼接到新的串中。
str.charAt(str.length - 1); 就是最后一位
str.charAt(str.length - 2) ;就是倒数第二位

function rev(char){
    var str = "";
    for(var i = char.length - 1 ; i >= 0 ; i--){
        str += char.charAt(i);
    }
    return str;
}

方法2:字符串 →数组str.split→ 倒置arr.reveer()→ 字符串arr.join(“”)

以后一看见倒置这个词,就要立即想到数组!
数组有一个东西,reverse()可以立即将数组倒置。

function rev(char){
	//字符串 → 数组
	var arr = char.split("");	//按字母拆开
	//数组倒置
	arr.reverse();
	//拼接成为字符串
	return arr.join("");
}

第4题

将字符串”i come from beijing“倒置,即控制台输出”beijing from come i

语句直接写在程序中,不需要用户输入。

<script type="text/javascript">
	var str = "i come from beijing";
	//字符串 → 数组
	var arr = str.split(" ");
	//数组倒置
	arr = arr.reverse();
	//数组 → 字符串
	str = arr.join(" ");

	alert(str);
</script>

第5题

编写函数rightchange(char,n) 实现字符串char循环右移n位。

比如rightchange("abcdefg",2)返回”fgabcde”。

方法1:就是大家想到的用数组,因为数组有popunshift();

arr.unshift(arr.pop()):把最后一位挪到第1位。

function rightchange(char,n){
	//转为数组
	var arr = char.split("");
	//循环执行右移
	for(var i = 1 ; i <= n ; i++){
		arr.unshift(arr.pop());
	}
	return arr.join("");
}

方法2:原来:abcdefg (移动2) ,变为:fgabcde

fgabcde = fg + abcde = abcdefg.substr(-2) + abcdefg.substr(0 , length - 2);
移动a就是:原.substr(-a) + 原.substr(0 , length - a);

function rightchange(char,n){
	n = n % char.length;	//子串长度7,移动8位,等于移动1位
	if(n == 0) return char;	//移动0位,就是返回原字符串	
	return char.substr(-n) + char.substr(0,char.length - n);
	}

第6题

编写函数maxr(char)返回字符串char中最长的连续重复字母。

比如maxr("mmmiijjjjkkkkkkssptr")返回"kkkkkk"

//双指针法,返回字符串char中最长的连续重复字母

function maxr(char){
	//两个指针
	var a = 0;
	var b = 1;	//b的初始位置就是a的右边1位
	var maxLength = 0; 	//重复的最大的数量
	var maxletter = "";  //重复数量最多的字母

	//循环一直做一直做,直到a指针指向了最后字母
	while(a != char.length - 1){
		//判断,两个指针指向的字母是否一样
		if(char.charAt(b) == char.charAt(a)){
			//两个指针指向的字母是相同的,那么b指针右移
			b++;
		}else{
			//两个指针指向的字母不同
			//和当前最大的进行比较
			if(b - a >= maxLength){
				//两个指针之间的距离比最大的还大,现在的b-a就是最大的距离
				maxLength = b - a;
				maxletter = char.charAt(a);	//a指针指向的就是这个字母
			}

			//让a指针右移
			//b指针也要跟着复位,就是a+1的位置
			a++;
			b = a + 1;
		}
	}
	return maxletter;
}

第7题

有10个学生的成绩存在数组中,请统计大于等于平均成绩的人数。

成绩直接以数组形式写在程序中,不需要用户输入。

var scoreArr = [6,45,23,56,76,89,34,23,65,23];

//统计平均成绩,就要有总成绩
var sum = 0;
for(var i = 0 ; i <= scoreArr.length - 1 ; i++){
	sum += scoreArr[i];
}

//平均成绩
var average = sum / scoreArr.length;

//大于等于平均成绩的人数
//又需要一个循环
var count = 0;
for(var i = 0; i <= scoreArr.length - 1 ; i++){
	if(scoreArr[i] >= average){
		count++;
	}
}

alert("大于等于平均成绩的人数" + count);

第8题

有10个学生的成绩存在数组中,请统计最高分,最低分,并将最高分和最低分学生的下标输出到控制台。

//有10个学生的成绩存在数组中,请统计最高分,最低分,并将最高分和最低分学生的下标输出到控制台

var scoreArr = [6,45,23,56,76,89,34,23,65,23];

//最大值最小值
var max = 0;		//如果你这个成绩比max还大,那么你就成为max
var min = 100;		//如果你这个成绩比min还小,那么你就成为min

var maxindex = 0;	//最大数字的下标
var minindex = 0;	//最小数字的下标

//经典的找数组中最大值的方法
for(var i = 0 ; i < scoreArr.length ; i++){
	//如果这个值比max还大,那么你就成为max
	if(scoreArr[i] > max){
		max = scoreArr[i];
		maxindex = i;
	}
	//如果这个值比min还小,那么你就成为min
	if(scoreArr[i] < min){
		min = scoreArr[i];
		minindex = i;
	}
}

console.log("最大数" + max, "最小数" + min,"最大数下标" + maxindex,"最小数下标" + minindex);

第9题

勾股定理:直角三角形中,两个直角边的平方和,等于斜边平方和。寻找三边的长度都不大于100,并且三边边长都是整数的可能,在控制台输出。

方法1:穷举法

for(var a = 1 ;  a <= 100 ; a++){
	for(var b = 1 ;  b <= 100 ; b++){
		for(var c = 1 ;  c <= 100 ; c++){
			if(a * a + b * b == c * c){
				console.log(a , b ,c);
				break;
			}
		}
	}
}

方法2:设A验B

for(var a = 1 ; a <= 100 ; a++){
	for(var b = 1 ; b <= 100 ; b++){
		var c2 = a * a + b * b;	//c的平方
		//判断c2的平方根是不是整数,就是判断c是不是整数
		var c = Math.sqrt(c2);
		if(c == parseInt(c) && c <= 100){
			console.log(a , b ,c);
		}
	}
}