此文章为学习笔记,非原创,侵删
数组中出现次数超过数组长度一半的数字
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组[1,2,3,2,2,2,5,4,2]。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
思路
解法1
- 新建一个对象
object - 循环数组
object的key为当前值,value为当前值存在的次数
时间复杂度为 O(n)
function MoreThanHalfNum_Solution(numbers){
if (numbers && numbers.length > 0) {
var length = numbers.length;
var temp = {};
for (var i = 0; i < length; i++) {
if (temp['s' + numbers[i]]) {
temp['s' + numbers[i]]++;
} else {
temp['s' + numbers[i]] = 1;
}
if (temp['s' + numbers[i]] > length / 2) {
return numbers[i];
}
}
return 0;
}
}
解法2
- 目标值的个数比其他所有值出现的次数之和多。例如题目中2出现的次数比1,3,5,4出现的次数之和要多
- 符合要求的数一定会重复连续出现,例如题目中的2连续出现了3次
- 记录两个变量:数组中的某个值
target和次数count - 当前值和上次一遍历的值相等?次数+1 : 次数-1
count为0后target变为新的值(符合要求的数一定会重复连续出现,例如题目中的2连续出现了3次)- 遍历结束后保存的值,判断是否符合条件
时间复杂度为 O(n)
function MoreThanHalfNum_Solution(numbers) {
if (numbers && numbers.length > 0) {
var target = numbers[0];
var count = 1;
for (var i = 1; i < numbers.length; i++) {
if (numbers[i] === target) {
count++;
} else {
count--;
}
if (count === 0) {
target = numbers[i];
count = 1;
}
}
count = 0;
for (var i = 0; i < numbers.length; i++) {
if (numbers[i] === target) count++;
}
return count > numbers.length / 2 ? target : 0;
}
}
连续子数组的最大和
输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值,要求时间复杂度为O(n)
例如:[6,-3,-2,7,-15,1,2,2],连续子子数组的最大和为8(从第0个开始,到第3个为止)
思路
- 记录当前连续子数组的最大值
max默认值为数组第一项 - 记录当前连续子数组累加值
sum默认值为数组第一项 - 从数组第二项开始遍历,判断
sum的值 - 当
sum<0,则当前的sum不再向后边的累加,切设置sum=当前值 - 当
sum>=0,则sum=sum+当前值 - 当
sum和max,max=两者最大值
function FindGreatestSumOfSubArray(array) {
if (Array.isArray(array) && array.length > 0) {
let sum = array[0];
let max = array[0];
for (let i = 1; i < array.length; i++) {
if (sum < 0) {
sum = array[i];
} else {
sum = sum + array[i];
}
if (sum > max) {
max = sum;
}
}
return max;
}
return 0;
}
扑克牌顺子
扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。
2-10为数字本身,A为1,J为11...大小王可以看成任何数字,可以把它当作0处理。
思路
- 数组排序,排序后数组变为有序数组。然后只需要查看大小王的个数是不是符合间隔数值的和即可
- 遍历数组
- 大小王作为0处理,记录0的个数
- 记录所有数之间的间隔
- 比较间隔数和大小王的个数是否相同
- 如果相同则说明是顺子
- 注意:连续出现两个相同的不为0的数字就不会是顺子了
function IsContinuous(numbers) {
if (numbers && numbers.length > 0) {
numbers.sort();
let kingNum = 0;
let spaceNum = 0;
for (let i = 0; i < numbers.length - 1; i++) {
if (numbers[i] === 0) {
kingNum++;
} else {
const space = numbers[i + 1] - numbers[i];
if (space == 0) {
return false;
} else {
spaceNum += space - 1;
}
}
}
return kingNum - spaceNum >= 0;
}
return false;
}
第一个只出现一次的字符
在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回-1(需要区分大小写)
思路
解法1
- 用一个object存储每个字符出现的次数,
key为字符,value为次数 - 遍历数组,存储次数生成object
- 遍历object,找到第一个出现一次的字符
时间复杂度O(n) 空间复杂度O(n)
function FirstNotRepeatingChar(str) {
if (!str) {
return -1;
}
let countMap = {};
const array = str.split('');
const length = str.length;
for (let i = 0; i < length; i++) {
const current = array[i];
let count = countMap[current];
if (count) {
countMap[current] = count + 1;
} else {
countMap[current] = 1;
}
}
for (let i = 0; i < length; i++) {
if (countMap[array[i]] === 1) {
return i;
}
}
return -1;
}
解法2
- 使用js数组的方法
indexOf和lastIndexOf - 遍历字符串,比较每个字符串第一次出现的位置和最后一次出现的位置是否相同
- indexOf的时间复杂度为
O(n),所以整体的时间复杂度为O(n2),空间复杂度为0。
function FirstNotRepeatingChar(str) {
// write code here
for (var i = 0; i < str.length; i++) {
if (str.indexOf(str[i]) == str.lastIndexOf(str[i])) {
return i;
}
}
return -1;
}