【77】JS数组 函数 对象 算法练习题(小白思路VS更优思路)
★文章内容学习来源:拉勾教育大前端就业集训营
本篇学习目标:
1.识别小白思路之弊端,掌握更优思路
一、数组
1. 统计大于等于平均成绩的人数
- 有10个学生的成绩存在数组中,请统计大于等于平均成绩的人数。
- 成绩直接以数组形式写在程序中,不需要用户输入。
这一题比较基础,涉及数组的定义以及数组长度与项之间关系:
var grades = [60,70,80,56,38,95,67,88,100,75];
//console.log(grades);
sumgrades = 0;
for (i = 0 ; i <= grades.length-1 ; i++) {
sumgrades += grades[i];
}
//console.log("所有人分数之和="+sumgrades);
var av = sumgrades / grades.length;
// console.log("平均分="+av);
//计数:大于平均分的人数
var count =0;
for (i = 0 ; i <= grades.length-1 ; i++) {
if (grades[i] > av) {
count++;
}
}
console.log("大于等于平均成绩"+av+"的人数有"+count+"人");
2. 数组中的最大值和最小值,以及所在位置的下标
- 求一组数中的最大值和最小值,以及所在位置的下标。
比较简单的方法如下,灵活运用中间变量:
var arr = [2,4,1,5,3,9,10,8,7,6];
console.log(arr);
//定义中间变量,储存比较过程中的最大值最小值以及对应下标
var max = 0; //最大值的初始值必须是最小的
var min = 20; //最小值的初始值必须是最大的
var max_index = 0;
var min_index = 0;
//循环遍历数组进行比较
for (var i = 0; i <= arr.length-1 ; i++) {
//比较是否比最大值更大
if (arr[i] > max) {
max = arr[i];
max_index = i;
}
//比较是否比最小值更小
if (arr[i] < min) {
min = arr[i];
min_index = i;
}
}
//输出
console.log("最大值"+ max+"所在下标为"+max_index);
console.log("最小值"+ min+"所在下标为"+min_index);
也可以用到内置对象中的一些方法:
//①定义一组数
var arr = new Array(2,4,1,5,3,9,10,8,7,6);
console.log(arr);
//②数组转字符串,之后找位置可以借助字符串,因为数组排序后顺序会变
var char = arr.join("");
//console.log(char);//转数组成功
//③从大到小给数组排序
arr.sort(function(a,b) {
if (a > b) {
return -1; //a在b前,越大越在前,说明是从大到小排序
} else if (a < b) {
return 1; //a在b后
} else {
return 0; //a和b保持原来位置
}
});
//④排序后数组的第一个是最大值,最后一个是最小值//数组顺序变了,所以从之前转号的字符串中找两个值所在位置
console.log("最大值"+arr[0]+"所在位置下标"+char.indexOf("10"));
console.log("最小值"+arr[arr.length-1]+"所在位置下标"+char.indexOf("1"));
二、函数
1.完美数
- 使用函数方法书写一段程序,判断一个数是不是完美数。 如果一个数恰好等于它的因数之和,则称该数为“完美数”。
- 例如:第1个完全数是6,它有因数1、2、3、6,除去它本身6外,其余3个数相加,1+2+3=6。
小白思路:刚开始学习这里的我,容易写成以下形式,虽然也可以成功实现效果,但是违背了函数的作用:让函数的功能模块化(单一),并且可以尽量在任何需要它的地方再次调用。
function fun1 (a = prompt("请输入一个整数","6")) {
sum = 0;
for (i = 1; i <= a ; i++) {
if (a % i == 0) {
sum += i;
}
}
if (sum == 2*a) {
alert(a+"是完美数");
} else {
alert(a+"不是完美数");
}
}
fun1();
1.更优思路:需要把其中涉及到函数单独拎出来,模块化,实现单一的功能。
2.思考顺序: 判断→需要用户先输入→需要知道怎么判断完美数→需要知道约数和情况。而写代码实现思路与之相反~也就是逆向思维。
3.写代码实现顺序:设置约数和函数→设置判断完美数函数→用户输入→判断
4.虽然下例代码看起来更多,但是却可以在更多的场合调用,真正实现了函数的作用。
//约数和函数(约数和情况)
function yueshuhe(a) {
//累加器
sum = 0;
for (var i = 1; i < a ; i++) {
if (a % i === 0){
sum += i;
}
}
//循环结束后,sum中储存了a的约数和
return sum;
}
//判断完美数函数(怎么判断完美数)
function isWm(a) {
if (yueshuhe(a) === a) {
return true;
}else {
return false;
}
}
//用户输入
var n = parseInt(prompt("请输入一个数,会自动判断其是否为完美数","6"));
//判断用户输入是否为完美数并且弹出结果
if (isWm(n)){
alert(n+"是完美数");
} else {
alert(n+"不是完美数");
}
2. 盈数
- 求2000 以内的全部亲密数。
- 盈数是一种特殊的自然数,除去它本身以外的一切正约数的和大于它本身。与完美数类似。
小白思路:刚开始学习这里的我,容易写成以下形式,虽然也可以成功实现效果,但是违背了函数的作用:让函数的功能模块化(单一),并且可以尽量在任何需要它的地方再次调用。与上题犯错情况类似。
function fun () {
for (a = 1 ; a < 100; a++) {
sum = 0; //累加器初始化位置很重要!因为每次是一个a对应它所有的i(因数)之和,所以再a的循环之内
for(i = 1 ; i < a ; i++) {
if (a % i == 0) {
sum += i;
//因为上面定义了i<a,所以这里的sum就是除了a本身的所有a的因数i之和
}
}
//console.log(a +"的因数和为"+sum);
if (sum > a ) {
console.log(a+"是盈数");
}
}
}
fun ();
1.更优思路:需要把其中涉及到函数单独拎出来,模块化,实现单一的功能。
2.思考顺序:输出盈数→需要知道怎么判断盈数→需要知道约数和情况
3.代码书写顺序:约数和函数→判断盈数函数→输出盈数函数→调用
//约数和函数(与上题一样):输入参数a,输出a的约数和
function yueshuhe(a) {
sum = 0;
for (var i = 1; i < a;i++) {
if (a % i === 0) {
sum += i;
}
}
return sum;
}
//判断盈数函数:
function isYs(a) {
if (yueshuhe(a) > a) {
return true;
}else {
return false;
}
}
//输出盈数函数:传入一个参数b,输出1-b之间所有盈数
function scYs(b) {
for (i = 1;i <= b; i++) {
if (isYs(i)) {
console.log(i+"是盈数");
}
}
}
//调用
scYs(100);
3. 1! + 2! + 3! + 4! + …… + n!
- 用户输入一个整数n,求1! + 2! + 3! + 4! + …… + n!的和。
小白思路:多分支语句+调用函数。
缺点:不易在其它需要用到的地方调用,函数模块化的作用未能很好体现。
function fun (a = parseInt(prompt("请输入一个整数n","4"))) {
if (a == 1) {
return 1*1;
} else if (a == 2) {
return 1*1 + 2*1;
} else if (a > 2) {
return a*(fun(a-1)-fun(a-2)) + fun(a-1);
}
}
alert("1!+2!+……+n!="+fun());
更优思路:函数模块化。
//求阶乘函数(输入一个数,返回这个数的阶乘)
function jc(a) {
//累乘器
var mul = 1;
for (var i =1; i <= a;i++) {
mul *= i;
}
return mul;
}
//求阶乘和函数(传输一个整数a,返回从1!加到a!的和)
function jch(a) {
//累加器
var sum = 0;
for (var i =1; i <= a ;i++) {
sum += jc(i);
}
return sum;
}
//用户输入
var n = parseInt(prompt("请输入一个整数","4"));
//调用阶乘和函数
alert("1!+2!+……+n!="+jch(n));
4. 喇叭花数
- 求一个三位数,叫做“喇叭花数”,该三位数等于其每位数字的阶乘之和。
- 输出100~999的所有喇叭花数。
小白思路:仍然是与上几道题一样的情况,没有很好地把函数模块化的特点显示出来。
//求一个三位数,叫做“喇叭花数”,该三位数等于其每位数字的阶乘之和。
function fun () {
for (a = 100 ; a <= 999; a++) {
var g = a % 10,
s = parseInt(a / 10) % 10,
b = parseInt(a / 100);
//console.log(a+"个位为"+ g);
//console.log(a+"十位为"+ s);
//console.log(a+"百位为"+ b);
mulg = 1;
for (var i = g; i >= 1 ; i--) {
mulg *= i;
}
//console.log(a+"个位数的阶乘为"+mulg);
muls = 1;
for (j = s; j >= 1; j--) {
muls *= j;
}
//console.log(a+"十位数的阶乘为"+muls);
mulb = 1;
for (h = b; h >= 1; h--) {
mulb *= h;
}
//console.log(a+"百位数的阶乘为"+mulb);
//判断各个位数的阶乘之和是否等于这个数,是的话输出为喇叭花数
if (a == mulg + muls + mulb) {
console.log(a+"是喇叭花数");
}
}
}
fun();
更化思路:将第3题中遇见的求阶乘函数运用在其中,且再定义一个判断喇叭花数的函数。更能体现出函数的作用。
//思路:输出100~999的所有喇叭花数→需要知道怎么判断喇叭花数→需要知道一个数的阶乘怎么求
//阶乘函数
function jc(a) {
mul = 1;
for (i = 1;i <= a;i++) {
mul *= i;
}
return mul;
}
//判断喇叭花数函数
function isLbh(i) {
//拆分位数
var g = i % 10;
var s = parseInt(i / 10) % 10;
var b = parseInt(i / 100);
//计算各个位数阶乘之和
var sum = jc(g)+jc(s)+jc(b);
//判断与i是否相等
if (sum === i) {
return true;
} else {
return false;
}
}
//输出100~999的所有喇叭花数
for (var j = 100; j <= 999; j++){
if (isLbh(j)){
console.log(j+"是喇叭花数");
}
}
5. 亲密数
- 求2000 以内的全部亲密数。
- 如果整数A 的全部约数(包括1,不包括A 本身)之和等于B,且整数B 的全部约数(包括1,不包括B 本身)之和等于A,则称整数A和B是一对亲密数。
更优思路:因为以上几道题都展示了小白思路,总的来说就都是不具有函数模块化的思想,所以我们要额外注意这一点,那这里就直接展示更有思路啦!
// 思路:输出亲密数 → 判断亲密数 → 约数和函数
// 求约数和函数
// 说明:传入一个整数,返回这个整数的约数和
function yueshuhe(a) {
var sum = 0;// 累加器
// 循环累加约数
for(var i = 1 ; i < a ; i++){
if(a % i === 0){
sum+=i;
}
}
// 循环结束后,sum 中存了 a 的约数和
return sum;
}
// 制作判断亲密数函数
// 说明:输入一个数,判断是否有亲密数
function isQm(a) {
// 一个数如果有亲密数,那么这个亲密数肯定是 a 的约数和
// 直接求 a 的约数和
var b = yueshuhe(a);
// 反推 b 的约数和是否等于 a,如果相等就是亲密数,a 不能等于 b
if (yueshuhe(b) === a && a != b) {
return true;
}else{
return false;
}
}
// 直接输出 2000 以内的亲密数
for (var i = 1 ; i <= 2000 ; i++) {
var j = yueshuhe(i);
if (isQm(i) && j <= 2000) {
console.log(i+"和"+j+"是亲密数");
}
}
6.验证哥德巴赫猜想
- 哥德巴赫猜想:一个偶数可以拆分成两个质数之和。
更优思路:
// 用户输入
var n = parseInt(prompt("请输入一个大于2的偶数"));
// 判断质数函数
// 说明:输入一个数,返回是否是质数
function isZs(a) {
// 循环累加,看在 2 到根号 a 之间有没有其他约数,有就肯定不是质数,直接返回
for (var i = 2 ; i <= Math.sqrt(a) ; i++) {
if(a % i === 0){
// 说明肯定不是质数
return false;
}
}
// 如果能走到这个位置,说明没遇到 return,没有其他的约数,就是质数
if (a != 1) {
return true;
}else{
return false;
}
}
// 输出 n 的所有质数之和的可能性
for (var i = 2 ; i <= n / 2 ; i++) {
// 定义另一个质数可能性
var j = n - i;
// 判断 i 和 j 同时都是质数,输出
if (isZs(i) && isZs(j)) {
console.log(n + "可以拆分成两个质数" + i + "与" + j + "的和");
}
}
三、数组与函数综合
1. 买卖股票的最大利润
给定一个数组,它的第i个元素是一支给定股票第i天的价格。
如果你最多只允许完成一笔交易(即买入和卖出一支股票一次)设计一个算法来计算你所能获取的最大利润。
注意:你不能再买入股票前卖出股票!
示例:输入:[7, 1, 5, 3, 6, 4]输出:5
解释:在第2天(当天股票价格等于1)的时候买入,在第五天(当天股票价格等于6)的时候卖出,最大利润为 6 - 1 = 5。
注意:利润不能使7 - 1 = 6,因为第二天的价格为1,第一天的价格为7,你是不可能在第二天买入股票然后等到第一天卖出的。
function shares(arr) {
var max_out = 0;//最大利润的初始值
var max_in = arr[0];//买入价初始值
for (var i = 1; i <= arr.length -1;i++) {
if (arr[i] < max_in ){
max_in = arr[i]; //买入价有更低的了,所以替换
}
if (arr[i] - max_in > max_out){
max_out= arr[i]-max_in; //利润有更大的了,所以替换
}
}
return max_out; //返回最大利润值
}
//定一个一个数组调用函数
var arr = [7, 1, 5, 3, 6, 4];
console.log(shares(arr));
2. 去除数组中指定数
将数组中值为 0 的项去掉,将不为 0 的值存入一个新的数组,生成新的数组。
小白思路:单一实现某数组中的0项去掉。
更优思路:如下,考虑成一个具有指定项去除的功能的函数,下次调用函数用在别的数组中去除别的指定数也一样可行。
//定义此功能函数removeN(arr,num)
//说明:arr是数组,num是指定要去除的项
function removeN(arr,num) {
var newArr = [];//空数组用于将来接受去除num后的所有项,形成新数组
//遍历数组
for (var i = 0 ; i <= arr.length-1;i++) {
//如果原数组中遇到不是num的项,则加入到新数组中
if (arr[i] != num) {
newArr.push(arr[i]);
}
}
return newArr;
}
var arr = [0,2,0,0,0,0,70,0,0,0,0,9,44,0,0,0];
//调用函数num=0
console.log(removeN(arr,0));
四、对象
1. 数组去重
比如数组 [1,1,1,2,2,3,4,5,6,3,4,2,4,1]去重结果为 [1,2,3,4,5,6]
这一类题,老师说面试常考哦!目前所学知识可以想到以下两种方法。
方法1:利用内置对象数组的
splice
方法,for循环与条件分支if语句
var arr = [1,1,1,2,2,3,4,5,6,3,4,2,4,1];
console.log(arr);
//比较第i项和后面项是否相同,如果相同就删除后面项
function uique(arr) {
for (var i = 0; i < arr.length; i++) {
//比较
for (var j = i + 1; j < arr.length;j++) {
//如果前后相同,删除后一项
if (arr[i] === arr[j]) {
arr.splice(j,1);
j--; //因为后一项被删除了
}
}
}
return arr;
}
console.log(uique(arr));
方法2:利用内置对象数组的
indexOf
方法
var arr = [1,1,1,2,2,3,4,5,6,3,4,2,4,1];
console.log(arr);
function unique(arr) {
//定义一个新数组去接收不重复部分
var newArr = [];
//循环遍历有重复的数组
for (var i = 0; i < arr.length; i++) {
//如果i项不存在新数组中,就加入
if (newArr.indexOf(arr[i] )=== -1) {
newArr.push(arr[i]);
}
}
return newArr;
}
console.log(unique(arr));
2. 数组转对象
- [‘a’,‘a’,‘a’,‘b’,‘b’,‘c’,‘c’,‘c’,‘c’,‘d’,‘d’,‘d’,‘d’] —> {a: 3,b: 2,c: 4,d: 4}
相当于给一个空对象添加数据。
arr = ['a','a','a','b','b','c','c','c','c','d','d','d','d'];
console.log(arr);
//定义一个作用是数组转成对象的函数,其参数arr是数组
function transformToObj(arr) {
//定义一个空对象,用于接受数据
var obj ={
};
//循环遍历数组
for (var i =0; i < arr.length; i++) {
//如果数组中的项在对象中不存在,那就给这个属性值赋值为1
if (!obj[arr[i]]) {
obj [arr[i]] = 1;
}else {
//反之,如果数组中的项在对象中存在,那就在原有基础上+1
obj [arr[i]] +=1;
}
}
return obj;
}
console.log(transformToObj(arr));
3 .数组排序
- [3,4,1,2,6,5,8,9,10,7] —> [1,2,3,4,5,6,7,8,9,10]
错误示例:直接使用sort()方法,不做任何更改
因为sort是默认按照unicode编码大小排序的
var arr1 = [3,4,1,2,6,5,8,9,10,7];
//方法1:sort()方法
function paixu(arr) {
arr.sort();
return arr;
}
console.log(paixu(arr1));
正确示例:使用sort()方法时,更改其中参数关系。
可以参见【76】二、内置对象2. Array对象(3) 数组常用方法及举例⑥顺序相关sort()
- 简单来说:返回值是负数:a排在b前面。返回值是正数:a排在b后面。返回值是0:a和b的顺序保持不变。
var arr1 = [3,4,1,2,6,5,8,9,10,7];
//方法1:sort()方法
function paixu(arr) {
arr.sort(function(a,b){
return a-b; //只有a比b小,才会是负值,a排在前,所以从小到大排序
});
return arr;
}
console.log(paixu(arr1));
纯数字数组排序还有其它方法,以下介绍三种:冒泡排序、选择排序、插入排序。
冒泡排序: 具体介绍可以参见百度。
一般把数组原先的顺序按照垂直方向写,从底到顶依次写好,从第一项开始,两两比较,大的往上拿,最后大的都在数组后面,也就是从小往大排序。
//冒泡排序
var arr = [3,4,1,2,6,5,8,9,10,7];
//外层:冒泡次数=项数-1,所以i<arr.length
for (var i = 1; i < arr.length; i++) {
//内层:第i次冒泡要比较arr.length-i次
//第1次冒泡,要比较9次
//第2次冒泡,要比较8次
//第7次冒泡,要比较7次
//...
for(var j = 0; j < arr.length-i; j++){
//如果前项数>后一项,那就把大的前一项往后拿
if (arr[j] > arr[j+1]) {
var jval = arr[j]; //先把大的前一项赋值给中间变量
arr[j] = arr[j+1]; //再让小的后一项负值给前一项位置
arr[j+1] = jval; //最后让大的值赋值给后一项位置
}
}
}
console.log(arr);
选择排序:从下标为0的(也就是第一项)开始作为对比项,与其后所有项对比,其后所有项中最大的数作为目标项,目标项和对比项交换下标(也就是换位置)。
var arr = [3,4,1,2,6,5,8,9,10,7];
//对比项循环,从下标为0开始,到倒数第二项为止,如果到最后一项就没有目标项了
for (var i = 0; i < arr.length-1; i++) {
//记录一下当前对比项的下标i,当作判断依据
var m = i; //也默认第i项最大
//判断i以后的所有项中,有没有比第i项大,如果有,替换掉下标
//也就是寻找目标项
for (var j = i+1; j < arr.length; j++) {
if (arr[j] > arr[m]) {
//如果这里的判断条件改为小于号,则为小的往前移,相当于从小往大排序
m = j; //大的往前移,相当于从大到小排序
}
}
//如果这时候的m=j与原先的i不等(也就是位置不一样),就替换位置,利用中间变量old
if (m !== i) {
var old = arr[i]; //让i位置的值(对比项)赋值给old
arr[i] = arr[m]; //让m位置的值(目标项)赋值给i位置
arr[m] = old; // 让old(此时里面储存着原先的对比项值)赋值给m位置
}
}
console.log(arr);
插入排序:从第2项(也就是arr[1])开始往前比,大的往后挪
var arr = [3,4,1,2,6,5,8,9,10,7];
//外层循环从下标为1的项开始,与前比较
for (var i = 1; i < arr.length; i++) {
//定义一个对比项下标
var m = i - 1; //因为是往前比
//记录当前循环到的数据项,因为这一项可能会被替换掉,而后面可能要插入到别的位置
var current = arr[i];
//判断i以前的项,有无比i项大的,有则往后排
//最终到下标为0结束,如果期间遇见比i小的,则停止循环判断
while (m >= 0 && arr[m] > current) {
arr[m+1] = arr[m]; //往后排
m--;
}
//循环结束后,要么m=-1,要么就是当前的m项比i项小
arr[m+1] = current; //将原来的i项插入到m项之后
}
console.log(arr);
4. 将数组用 | 或其他符号连接成一个字符串
小白思路:可以实现效果,但是不如更优思路可重复利用性高。
//思路:①定义一个数组
var arr =[1,2,3,4,1,5,4];
//输出数组
console.log(arr);
//思路:②用数组的join方法转成字符串
char = arr.join("|");
//输出字符串
console.log(char);
更优思路1:将此功能定义给函数,直接使用join方法
var arr = [1,2,3,4,1,5,4];
//方法1,将此功能定义给函数,直接使用join方法
//函数说明:两个参数,arr数组,mark连接的符号
function connect(arr,mark) {
return arr.join(mark); //使用join方法直接转为字符串
}
console.log(connect(arr,"|"));
更优思路2:将此功能定义给函数,数组遍历
//方法2:数组遍历
function connect(arr,mark) {
var str = "" +arr[0]; //+的拼接功能,只要有一边是字符串,那整体结果就是字符串
//是从下标为1开始的左边有mark的
for (var i = 1; i < arr.length; i++) {
str += mark + arr[i] ;
}
return str;
}
console.log(connect(arr,"|"));
5. 实现将字符串倒置
- 编写函数rev(char) 实现将字符串char倒置,比如rev(“spring”) 返回"gnirps"。
小白思路:如下用了函数,也做到了模块化,但是还是可以优化!
var char = "spring";
console.log(rev(char));
function rev(char) {
//思路:可以先把字符串转换为数组,数组中有reverse()方法,然后再把数组转回字符串:
//转为数组
var arr = char.split("");
//数组倒序
arr.reverse();
//数组转为字符串
char =arr.join("");
return char;
}
更优思路:链式调用
因为以上用到的内置对象的方法中,都有返回值,可以直接进行调用,优化如下
var char = "spring";
console.log(rev(char));
function rev(char) {
return char.split("").reverse().join("");
}
6. 将字符串语句倒置
- 将字符串"i come from beijing"倒置,即控制台输出"beijing from come i"
- 语句直接写在程序中,不需要用户输入
小白思路:可以实现效果,但是不利于复用,同时也可以和上题一样考虑一下链式调用。
//定义字符串
var str = "i come from beijing";
console.log(str);
//将数组转为数组
var arr = str.split(" ");//以空格为分割
//console.log(arr);
//数组倒置
var rarr = arr.reverse();
//console.log(rarr);
//数组转回字符串
var str = rarr.join(" ");//以空格隔开
console.log(str);
更优思路:其实这题更多是考察能否在函数的参数中封装“分隔符”
var str = "i come from Beijing";
//函数说明:参数char是字符串,参数s是分割符
function rev(char,s) {
char = char.split(s).reverse().join(s);
return char;
}
console.log(rev(str," "));
7. 实现字符串循环右移n位
- 编写函数
rightchange(char,n)
实现字符串char循环右移n位。- 比如
rightchange("abcdefg",2)
返回"fgabcde"
小白思路:①字符串转为数组②尾删→首添③转回字符串,用了函数调用。
但代码量大,且不利于复用。
//思路:①字符串转为数组②尾删→首添③转回字符串
function rightchange (char,n) {
//输入字符串
var char = prompt("请输入一个字符串,会执行循环右移","abcdefg");
//①字符串转数组
var arr = char.split("");
console.log("第一次字符串转数组"+arr);//数组转成功
function xhws(n) {
if (n == 1) {
//②分支-循环右移1位:数组尾删的数加到首部
return arr.unshift(arr.pop());
} else if (n > 1) {
//②分支-右移大于1位:不断数组尾删的数加到首部,函数递归
return arr.unshift(arr.pop(xhws(n-1)));
}
}
//调用
xhws(n = prompt("请输入您要循环右移的位数","1"));
//输出右移数组
console.log("循环右移"+ n +"位后的数组"+arr);//右移成功
//③转回字符串
char = arr.join(""),
console.log("转回字符串的结果"+char);//转回字符串成功
alert(char);
}
rightchange();
更优思路1:用for循环来进行需要重复的
unshift
,pop
方法,整体一个函数更加清晰明了。
//定义函数
function rightChange(char,n) {
n = n % char.length; //根据多次右移发现这个规律,这样循环次数可以减少
var arr = char.split("");//字符串转数组
//循环让数组尾删→首添n次
for (var i = 1; i <= n ;i++) {
arr.unshift(arr.pop());
}
char = arr.join(""); //数组转回字符串
return char;
}
//调用函数
var char = prompt("请输入一个字符串","abcdefg");
var n = parseInt(prompt("请输入您想右移的位数","1"));
alert(rightChange(char,n));
更优思路2:根据n的数值,字符串截取(截成两段),之后把两段颠倒顺序再拼接
//方法2:根据n的数值,字符串截取(截成两段),之后把两段颠倒顺序再拼接
function rightChange(char,n) {
n = n % char.length;
var str1 = char.slice(0,-n);//开始于第0位,截止于从后往前数第n位(不包括)。
var str2 = char.slice(-n);//开始于从后往前数第n位,截止于结束。
char = str2 + str1;
return char;
}
var char = prompt("请输入一个字符串","abcdefg");
var n = parseInt(prompt("请输入您想右移的位数","1"));
alert(rightChange(char,n));
8. 返回字符串中最长的连续重复字母
- 编写函数
maxr(char)
返回字符串char中最长的连续重复字母。
常见思路:二指针法:一个基准值,一个移动,同时使用中间变量存储过渡值(最长子串,最长长度)。
情况1:一个字符串中只有一个最长连续重复字母:
比如maxr("mmmiijjjjkkkkkkssptr")
返回"kkkkkk
"
console.log(maxr("mmmiijjjjkkkkkkssptr"));
function maxr(char) {
var a = 0,//基准值
b = 1;//移动
var maxLength = 0;//最长子串长度,初始值0
var maxChar = ""; //最长子串,初始值""
//基准值的循环从0开始,到倒数第二个结束
while (a <= char.length-2) {
//每次都比较a位置与b位置是否一样
if (char.charAt(a) === char.charAt(b)) {
//如果相等就给b加1,进入下一次循环
b++;
}else {
//不相等,则与原先的最长子串比较,存储现最长子串情况
if (b - a > maxLength) {
maxLength = b - a;
maxChar = char.slice(a,b);
}
//a基准值该换位置了,储存完成这次数据,进入下一次比较时
a = b;
b = a + 1;
}
}
return maxChar;
}
情况2:一个字符串中不止一个最长连续重复字母:
比如maxr("mmmiijjjjkkkkkksssssspppppptr")
返回"kkkkkk
", “ssssss
”, “pppppp
”
解决办法:可以把maxChar定义为数组
console.log(maxr1("mmmiijjjjkkkkkksssssspppppptr"));
function maxr1(char) {
var a = 0,
b = 1;
var maxChar = [""]; //数组
var maxLength = 0;
while (a <= char.length -2) {
if (char.charAt(a) === char.charAt(b)) {
b++;
}else {
if (b -a > maxLength) {
maxLength = b - a ;
maxChar = [char.slice(a,b)];//数组中添加数据
} else if (b - a === maxLength) {
maxChar.push(char.slice(a,b));//在 maxChar数组中往后添加字符串数
}
a = b;
b = a + 1;
}
}
return maxChar;
}
9. 将一句英文每个单词的第一个字母,变为大写
- 比如将"i love javascript very much"的每个单词的第一个字母,变为大写。
//思路:转为数组→循环遍历数组将首字符大写并再拼接上原来首字母后面的→转回字符串
var char = "i love javascript very much";
console.log(char); //原字符串输出做对比
console.log(firstLetterup(char));//调用下面函数后
function firstLetterup(char) {
arr = char.split(" ") //字符串转数组,数组中每一项是以" "为分隔符隔开的
for (i = 0; i <= arr.length-1; i++) {
//具体的每一项还是个字符串可以用charAt方法定到首字母,用toUpperCase将其转为大写,但是整体上还需要拼接上原来每一项的除了首字母外的其它字符用+号和slice方法
//链式调用
arr[i]= arr[i].charAt(0).toUpperCase()+arr[i].slice(1);
}
str = arr.join(" ");//转回字符串
return str;
}
10. 九九乘法表
//思路:将乘法表横着看
//两层for循环,外层是1-9;
//内层对应外层,外层是几,内层就循环到几
for (var i = 1; i <= 9; i++) {
var str = " "; //字符串拼接,有点像“累加器”
for (var j = 1; j <= i; j++) {
str += i +"×"+j+"="+i*j+" ";
}
console.log(str+"\n"); //每循环一次外层,就换一次行
}
下篇继续:【xx】xxxxxxxxxx