刷题

53 阅读7分钟

数组的中心位

/**
 * 数组的中心位置
 * 给你一个整数数组nums,请计算数组的中心位置 。数组中心位置是数组的一个下标,其左侧所有元素相乘的积等于右侧所有元素相乘的积。
 * 数组第一个元素的左侧积为1,最后一个元素的右侧积为1
 * 如果数组有多个中心位置,应该返回最靠近左边的那一个。如果数组不存在中心位置,返回 -1 。

 * 输入描述:输入只有一行,给出N个正整数用空格分格:nums = 2 5 3 6 5 6
 * 1 <= nums.length <= 1024
 * 1 <= nums[i] <= 10
 * 
 * 
 * */

 function getMiddleIndex (list) {
 	const leftProduct = [1]
 	for (let i = 1; i < list.length; i++) {
 		const pre =  list[i - 1];
 		const product  = pre * leftProduct[i - 1]
 		leftProduct.push(product)
 	}
 	const rightProduct = [1]
 	for (let i = list.length - 2; i >= 0; i--) {
 		const pre =  list[i + 1];
 		const product  = pre * rightProduct[0]
 		rightProduct.unshift(product)
 	}
 	for (let i = 0; i < list.length; i++) {
 		if (leftProduct[i] === rightProduct[i]) {
 			return i
 		}
 	}
 	return -1
}

 const demoData = [
 	[2,5,3,6,5,6],
 	[1,1,1,1,1,1],
 	[11,22,333,3,3,3,0,23,44,5,0]
 ]

const result = []
 demoData.forEach((item) => {
 	const res = getMiddleIndex(item)
 	result.push(res)
 })
 console.log(result)

获取最大软件版本号

/**
 * 获取最大软件版本号
 * Maven版本号定义,<主版本>.<次版本>.<增量版本>-<里程碑版本>,举例3.1.4-beta
 * 其中,主版本和次版本都是必须的,主版本,次版本,增量版本由多位数字组成,可能包含前导零,里程碑版
 * 本由字符串组成。
 * <主版本>.<次版本>.<增量版本>:基于数字比较
 * 里程碑版本:基于字符串比较,采用字典序
 * 比较版本号时,按从左到右的顺序依次比较。基于数字比较, 只需比较忽略任何前导零后的整数值 。
 * 输入2个版本号,输出最大版本号
 * 
 * 版本号相同时输出第一个输入版本号
 * 
 * 主版本,次版本,增量版本:基于字符串比较,比如
 * 1.5>1.4>1.3.11>1.3.9
 * 里程碑版本:基于字符串比较 比如
 * 1.2-beta-3>1.2-beta-11
 * 
 * */

 function getBiggerVersion (v1, v2) {
 	const [version1, ...beta1] = v1.split('-')
 	const [version2, ...beta2] = v2.split('-')
 	const v1List = version1.split('.')
 	const v2List = version2.split('.')
 	if (beta1) {
 		v1List[3] = beta1.join('-')
 	}
 	if (beta2) {
 		v2List[3] = beta2.join('-')
 	}
 	
 	const maxLen = Math.max(v1List.length, v2List.length)
 	let i = 0
 	while(i < maxLen) {
 		if (!v1List[i] && !v2List[i]) {
			return v1
 		}
 		if (!v1List[i]) {
 			return v2
 		}
 		if (!v2List[i]) {
 			return v1
 		}
 		// 比较 主 次 增量
 		if (i < 3) {
 			const num1 = parseInt(v1List[i])
 			const num2 = parseInt(v2List[i])
 			if (num1 > num2) {
 				return v1
 			}
 			if (num1 < num2) {
 				return v2
 			}
 		} else {
 			return v1List[i] >= v2List[i] ? v1 : v2
 		}
 		i++
 	}
}

 const demoData = [
 	['1.5.3', '2.5'],
 	['1.2.3-a', '1.1'],
 	['1.5', '1.5.0'],
 	['1.1.01', '1.01.2'],
 	['1.1.1-beta-11', '1.1.1-beta-2'],
 	['1.1.1-beta-a', '1.1.1-beta-b'],
 	['1.1.1-beta-1a', '1.1.1-beta-a1'],
 ]

const result = []
 demoData.forEach((item) => {
 	const res = getBiggerVersion(item[0], item[1])
 	result.push(res)
 })
 console.log(result)

猜字谜

/**
 * 猜字谜
 * 小王设计了一个简单的猜字谜游戏,游戏的谜面是一个错误的单词,比如nesw,玩家需要猜出谜底库中正确的单词。猜中的要求如下:
 * 对于某个谜面和谜底单词,满足下面任一条件都表示猜中:
 * 	1)变换顺序以后一样的,比如通过变换w和e的顺序,“nwes”跟“news”是可以完全对应的;
 * 	2)字母去重以后是一样的,比如“woood”和“wood”是一样的,它们去重后都是“wod”\
 * 请你写一个程序帮忙在谜底库中找到正确的谜底。谜面是多个单词,都需要找到对应的谜底,如果找不到的话,返回"not found"
 * 
 * 1、谜面单词列表,以","分隔
 * 2、谜底库单词列表,以","分隔
 * 
 * 匹配到的正确单词列表,以“,”分隔
 * 如果找不到,返回"not found"
 * 
 * 1、单词的数量N的范围:0 < N < 1000
 * 2、词汇表的数量M的范围: 0 < M < 1000
 * 3、单词的长度P的范围:0 < P < 20
 * 4、输入的字符只有小写英文字母,没有其它字符
 * 
 * */

 function getAnswer (riddle, answers) {
    const answersList = answers.split(',')
 	const [answersCountWordMap, answersSimpleWordMap] = getMap(answersList)
 	const riddles = riddle.split(',')
 	const res = riddles.map((item) => {
 		const countWord = getCountWord(item)
        const simpleWord = getSimpleWord(item)
 		if (answersCountWordMap[countWord]) {
 			return answersCountWordMap[countWord]
 		} else if (answersSimpleWordMap[simpleWord]) {
            return answersSimpleWordMap[simpleWord]
        } else {
 			return 'not found'
 		}
 	})
 	return res.join(',')
 }

 function getMap (list)  {
 	const countWordMap = {}
    const simpleWordMap = {}
 	for (var i = 0; i < list.length; i++) {
 		const word = list[i]
 		const countWord = getCountWord(word)
        countWordMap[countWord] = word
        const simpleWord = getSimpleWord(word)
        simpleWordMap[simpleWord] = word
 	}
 	return [countWordMap, simpleWordMap]
 }

 function getSimpleWord(word) {
 	const len = word.length;
    let simpleWord = ''
    let pre = ''
	for (let j = 0; j < len; j++) {
		const cur = word[j]
        if (pre !== cur) {
            simpleWord += cur
            pre = cur
        }
	}
	return simpleWord
 }
 function getCountWord(word) {
    const len = word.length;
    const wordCount = []
    for (let j = 0; j < len; j++) {
        const index = word[j].charCodeAt() - 97
        if (wordCount[index]) {
            wordCount[index]++
        } else {
            wordCount[index] = 1
        }
    }
    let simpleWord = ''
    wordCount.forEach((item, index) => {
        if (item) {
            const char = String.fromCharCode(index + 97)
            simpleWord += `${char}${item}`
        }
    })
    return simpleWord
 }


 const demoData = [
 	['nwes', 'news'],
 	['woood', 'wood'],
 	['woood,wwwww', 'wood,w'],
 	['hesss,oeellhello', 'hello,wood'],
 	['woode', 'wood, wedo'],
 ]

const result = []
 demoData.forEach((item) => {
 	const res = getAnswer(item[0], item[1])
 	result.push(res)
 })
 console.log(result)

合并关联端口

/**
 * 合并关联端口
 * 有M(1<=M<=10)个端口组,每个端口组是长度为N(1<=N<=100)的整数数组。
 * 如果端口组间存在2个及以上不同端口相同,则认为这两个端口组互相关联,可以合并。
 * 第一行输入端口组个数M,再输入M行,每行逗号分隔,代表端口组,输出合并后的端口组用二维数组表示。
 *  
 * 端口组内数字可以重复
 * 
 * 1.组内相同端口仅保留一个,从小到大排序。
 * 2.组外顺序保持输入顺序
 * 
 * M,N不再限定范围内,统一输出一组空数组[[]]
 * 
 * 
 * */

 function getMergePorts (list) {
 	const [len, ...portGroupList] = list
 	if (len < 1 || len > 10) {
 		return [[]]
 	}
 	let i = 0;
	// 排序加去重
 	while(i < portGroupList.length) {
 		const group = portGroupList[i]
 		portGroupList[i] = Array.from(new Set(group)).sort((a, b) => a-b)
 		i++
 	}
 	// 开始合并
 	i = 0
    let j = i + 1;
 	while(i < portGroupList.length) {
 		let j = i + 1;
        let hasChange = false
 		while(j < portGroupList.length) {
 			const canMerge = isCanMerge(portGroupList[i], portGroupList[j]);
 			if (canMerge) {
                hasChange = true
 				portGroupList[i] = Array.from(new Set([...portGroupList[i], ...portGroupList[j]])).sort((a, b) => a-b)
 				portGroupList.splice(j, 1)
 			}
 			j++
 		}
        if (hasChange) {
            i = 0
        } else {
            i++
        }
 	}
 	
 	return portGroupList
 }

 function isCanMerge (a, b)  {
 	let sameNum = 0;
 	let i =0
 	let j = 0;
 	while (i < a.length && j < b.length) {
 		if (a[i] === b[j]) {
 			sameNum++
 			i++
 			j++
 		} else if (a[i] > b[j]) {
 			j++
 		} else {
 			i++
 		}
 		if (sameNum === 2) {
 			return true
 		}
 	}
 	return false
 }


 const demoData = [
 	// [4,[ 4 ], [ 2, 3, 2 ], [ 1, 2 ], [ 5 ]],
 	// [3, [ 2, 3, 1 ], [ 4, 3, 2 ], [ 5 ]],
 	// [6, [ 10 ], [ 4, 2, 1 ], [ 9 ], [ 3, 6, 9, 2 ], [ 6, 3, 4 ], [ 8 ]],
    [10, [1,2,3], [3],[2,3,4],[4],[3,4,5],[5],[6,7,8],[6],[9,8,7],[4,5,6,7]]
 ]

const result = []
 demoData.forEach((item) => {
 	const res = getMergePorts(item)
 	result.push(res)
 })
 console.log(result)

积木游戏

/**
 * 
 * 积木游戏
 * 第一行输入为N,表示小华排成一排的积木总数。
 * 接下来N行每行一个数字,表示小华排成一排的积木上数字。
 * 求相同数字的积木的位置最远距离;
 * 如果所有积木数字都不相同,请返回-1.
 *  
 * */

 function getMaxSameNumSpace (list) {
 	const spaces = []
 	const [len, ...other] = list
 	if (len !== other.length) {
 		return -1
 	}
 	other.forEach((num, index) => {
 		if (spaces[num]) {
 			spaces[num][1] = index
 		} else {
 			spaces[num] = [index]
 		}
 	})
 	let maxSpace = -1
 	spaces.forEach((item) => {
 		if (item && item.length === 2) {
 			const space = item[1] - item[0]
 			maxSpace = Math.max(maxSpace, space)
 		}
 	})
 	return maxSpace
 }


 const demoData = [
 	[5,1,2,3,1,4],
 	[2,1,2],
 ]

const result = []
 demoData.forEach((item) => {
 	const res = getMaxSameNumSpace(item)
 	result.push(res)
 })
 console.log(result)

匿名信

/**
 * 
 * 匿名信
 * 第一行输入newspaper内容,包括1-N个字符串,用空格分开
 * 第二行输入anonymousLetter内容,包括1-N个字符串,用空格分开
 * 1、newspaper和anonymousLetter的字符串由小写英文字母组成且每个字母只能使用一次
 * 2、newspaper内容中的每个字符串字母顺序可以任意调整,但必须保证字符串的完整性(每个字符串不能有多余字母)
 * 3、1<N<100,1<=newspaper.length,anonymousLetter.length<=10
 * 求报纸内容是否可以拼成匿名信。
 *  
 * */

 function canGetLetter (newspaper, anonymousLetter) {
 	const newspaperMap = getList(newspaper)
 	const anonymousLetterMap = getList(anonymousLetter)
 	console.log(newspaperMap, anonymousLetterMap)
 	const keys = Object.keys(anonymousLetterMap)
 	for (var i = 0; i < keys.length; i++) {
 		const simpleWord = keys[i]
 		const num = anonymousLetterMap[simpleWord]
 		if (newspaperMap[simpleWord] >= num) {
 			newspaperMap[simpleWord] -= num
 		} else {
 			return false
 		}
 	}
 	return true
 }

 function getList (list) {
 	const map = {}
 	for (var i = 0; i < list.length; i++) {
 		const word = list[i]
 		const len = word.length;
 		const wordCount = []
 		for (let j = 0; j < len; j++) {
 			const index = word[j].charCodeAt() - 97
 			if (wordCount[index]) {
 				wordCount[index]++
 			} else {
 				wordCount[index] = 1
 			}
 		}
 		let simpleWord = ''
 		wordCount.forEach((item, index) => {
 			if (item) {
	 			const char = String.fromCharCode(index + 97)
	 			simpleWord += `${char}${item}`
 			}
 		})
 		if (map[simpleWord]) {
 			map[simpleWord]++
 		} else {
 			map[simpleWord] = 1
 		}
 	}
 	return map
 }

 const demoData = [
 	{
 		newspaper: ['ab', 'cd'],
 		anonymousLetter: ['ba']
 	},
 	{
 		newspaper: ['ab', 'bcd', 'ef'],
 		anonymousLetter: ['cbd', 'fe']
 	},{
 		newspaper: ['ab', 'bcd', 'ef'],
 		anonymousLetter: ['cd', 'fe']
 	},{
 		newspaper: ['wood', 'wood', 'wood'],
 		anonymousLetter: ['wodo', 'wdoo']
 	},{
 		newspaper: ['wood'],
 		anonymousLetter: ['wodo', 'wdoo']
 	},
 ]

const result = []
 demoData.forEach((item) => {
 	const { newspaper, anonymousLetter } = item;
 	const res = canGetLetter(newspaper, anonymousLetter)
 	result.push(res)
 })
 console.log(result)