提示:
牛客网刷题总结
一、NC137 表达式求值
char[] c = s.toCharArray();//字符串转化为数组,里面存放char类型
字符变数字:char c=s.charAt(i);
number=c-‘0’//字符相减为两字符ascll码相减
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
二、NC91 最长递增子序列
HashMap<Integer,Integer> map = new HashMap<>();
map.put(1,1)
Integer key = map.getKey()
Integer value = map.getValue()
map.containsKey(1)//键中是否包含这个数据
map.get(1)//通过建拿值
map.isEmpty()//
map.size()
map.remove(1)//从建中删除
Map集合中没有迭代器Iterator,而Set具备迭代器Iterator
Map的遍历有两种方法,一种是keySet(),一种是entrySet()
- keySet写法1
Set<String> keys = hashMap.keySet();
// 获取Set集合的迭代器it
Iterator<String> it = keys.iterator();
// 通过迭代器遍历Set集合的每一个元素,也就是存入的键key
while(it.hasNext()){
String key = it.next();
//有了键,就可以通过map集合的get方法获取对应的值
String value = hashMap.get(key);
System.out.println(key + " : " + value);
}
- keySet写法2(常用)
// 先keySet()取出Map集合的所有键并转成Set集合
Set<String> keys = hashMap.keySet();
// 获取Set集合的迭代器it
Iterator<String> it = keys.iterator();
- 写法2再简化
Iterator<String> it = hashMap.keySet().iterator();
- entrySet写法1
// 先entrySet()取出Map集合的所有键值对并存入Set集合
Set< Map.Entry<String,String> > entrySet = hashMap.entrySet();
// 获取Set集合的迭代器it
Iterator< Map.Entry<String,String> > it = entrySet.iterator();
// 通过迭代器遍历Set集合的每一个元素,也就是存入的键值对
while(it.hasNext()){
Map.Entry<String, String> mey = it.next();
//getKey()和getValue是接口Map.Entry<K,V>中的方法,getKey()返回对应的键,getValue返回对应的值
String key = mey.getKey();
String value = mey.getValue();
System.out.println(key + " : " + value);
}
- entrySet写法二
// 先entrySet()取出Map集合的所有键值对并存入Set集合
Set< Map.Entry<String,String> > entrySet = hashMap.entrySet();
// 获取Set集合的迭代器it
Iterator< Map.Entry<String,String> > it = entrySet.iterator();
- 写法二简化
Iterator< Map.Entry<String,String> > it = hashMap.entrySet().iterator();
定义数组
int[] res = new int[N]//其中N为数组长度
按数值比较的字典序:
比如 123,2,23,213 字典序为:123,2,213,23
三、NC12 重建二叉树
给定节点数为 n 二叉树的前序遍历和中序遍历结果,请重建出该二叉树并返回它的头结点。
输入:
[1,2,4,7,3,5,6,8],[4,7,2,1,5,3,8,6]
返回值:
{1,2,3,4,#,5,6,#,7,#,#,8}
JavaScript slice() 方法
stringObject.slice(start,end)
要抽取的片断的起始下标。如果是负数,则该参数规定的是从字符串的尾部开始算起的位置。也就是说,-1 指字符串的最后一个字符,-2 指倒数第二个字符,以此类推。
JavaScript indexOf() 方法
stringObject.indexOf(searchvalue,fromindex)
该方法将从头到尾地检索字符串 stringObject,看它是否含有子串 searchvalue。开始检索的位置在字符串的 fromindex 处或字符串的开头(没有指定 fromindex 时)。如果找到一个 searchvalue,则返回 searchvalue 的第一次出现的位置。stringObject 中的字符位置是从 0 开始的。
function reConstructBinaryTree(pre, vin)
{
// write code here
if (pre.length === 0 || vin.length === 0) return null;
let root = new TreeNode(pre[0]);
let root_index = vin.indexOf(pre[0]);
root.left = reConstructBinaryTree(pre.slice(1, root_index + 1), vin.slice(0, root_index));
root.right = reConstructBinaryTree(pre.slice(root_index + 1), vin.slice(root_index + 1));
return root;
}
三、NC15 求二叉树的层序遍历
给定的二叉树是{3,9,20,#,#,15,7},
[
[3],
[9,20],
[15,7]
]
function levelOrder( root ) {
// write code here
if(root==null){return [];}
let result=[];
let queue=[root];
while(queue.length){
let temp=[];
let qlen=queue.length;
for(let i=0;i<qlen;i++){
let first=queue.shift();
temp.push(first.val);
if(first.left!=null){queue.push(first.left);}
if(first.right!=null){queue.push(first.right);}
}
result.push(temp);
}
return result;
}
module.exports = {
levelOrder : levelOrder
};
1、push()是用来在数组末端添加项,并且返回添加后数组的长度;
2、pop()在数组末端移除项,返回移除的数组元素;
3、unshift()在数组前端添加项,并且返回添加后数组的长度;
4、shift()在数组的第一个项(前端)移除,返回移除的数组元素。
四、NC93 设计LRU缓存结构
myMap.entries()
entries()方法返回一个新的包含 [key, value]的 Iterator对象,返回的迭代器的迭代顺序与 Map对象的插入顺序相同。
var myMap = new Map();
myMap.set('0', 'foo');
myMap.set(1, 'bar');
myMap.set({}, 'baz');
var mapIter = myMap.entries();
console.log(mapIter.next().value); // ["0", "foo"]
console.log(mapIter.next().value); // [1, "bar"]
console.log(mapIter.next().value); // [Object, "baz"]
var map=new Map();
值类型就是存储在栈上,引用类型是存储在堆上,但是有个很特殊的情况是,引用类型的名字,是存储在栈上,然后这个名字指向了堆上的一个地址,从而可以直接使用变量名,调用堆上的数据
值类型:
let a = 1;
let b = a;
a = 2;
console.log("a的值是:" + a);
console.log("b的值是:" + b);
那么引用类型呢:
let a = [1, 2];
let b = a;
a[0] = 0;
console.log("a的值是:" + a);
console.log("b的值是:" + b);
正如上面所说exports = module.exports,也就是说他们指向了堆空间的同一个东西,如果对exports进行赋值,那么exports的指向就不一样了,在另外的文件里面就无法再找到通过exports这个变量传递的东西,而module.exports是在执行模块代码中就将module传入到了函数中,所以即使module.exports的值改变也能够在其他文件中进行调用。
//test.js
exports.add = 100;
module.exports = 1;
//test1.js文件
let test = require("./test");
let p = test.add;
let b = test;
console.log("p的值是:" + p);
console.log("b的值是:" + b);
/*
输出结果是:
p的值是:undefined
b的值是:1
*/
可以看出,改变了module.exports的指向后,http://exports.xxx的值在其他文件中也无法调用。
本题解答:
function LRU( operators , k ) {
var map = new Map();
var temp;
var result = [];
for(let i = 0; i < operators.length; i++){
if(operators[i][0] === 1){
// map中已经存在该key,说明其对应value需要更新
if(map.has(operators[i][1])){
map.delete(operators[i][1]);
}else{ //map已满,需要找到最久未访问的删除后,再添加新键值对
if(map.size==k){
const iterator = map.entries();
map.delete(iterator.next().value[0]);
}
}
map.set(operators[i][1], operators[i][2]);
}else{
if(map.has(operators[i][1])){
//如果map中有需要查询的key,先保存其值再删除然后添加,可保证这次访问后该键值对为最新插入,不会在删除时误删
temp = map.get(operators[i][1]);
map.delete(operators[i][1]);
map.set(operators[i][1], temp)
result.push(temp);
}else{
result.push(-1);
}
}
}
return result;
}
module.exports = {
LRU : LRU
};
五、NC100 把字符串转化为整数(atoi)
要求:
1.去掉无用的前导空格
2.第一个非空字符为+或者-号时,作为该整数的正负号,如果没有符号,默认为正数
3.判断整数的有效部分:
3.1 确定符号位之后,与之后面尽可能多的连续数字组合起来成为有效整数数字,如果没有有效的整数部分,那么直接返回0
3.2 将字符串前面的整数部分取出,后面可能会存在存在多余的字符(字母,符号,空格等),这些字符可以被忽略,它们对于函数不应该造成影响
3.3 整数超过 32 位有符号整数范围 [−231, 231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231的整数应该被调整为 −231 ,大于 231 − 1 的整数应该被调整为 231 − 1
4.去掉无用的后导空格
示例:(对应3.1)
分析:
1、去掉首尾空格
1.1空字符\s 若干* 开头^ :(^\s*)
1.2或者: |
1.3空字符\s 若干* 结尾$ : (\s*$ )
去掉首尾空格:String.Trim = function(){return this.replace(/(^\s*)|(\s*$)/g, “”);}
PS:空字符包括空格、制表符、垂直制表符、换页符、换行符、回车符。
2、正则表达式修饰符:
- 修饰符 :i、g、m
i 执行对大小写不敏感的匹配。
g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
m 执行多行匹配。
3、字符串的寻找与匹配
3.1 .test() 方法用于检测一个字符串是否匹配某个模式,有匹配的值返回 true ,否则返回 false
示例:
var str="Hello world!";
var patt=/Hello/g;
var result=patt.test(str);
与这个表示式是等价的:(r.exec(s) != null)
.exec()返回一个数组存放匹配结果,如果未找到匹配返回null
3.2 indexOf()
返回某指定字符串首次出现的位置,若没出现返回-1
var str = "123";
console.log(str.indexOf("3") != -1 ); // true
六、NC28 最小覆盖子串
1、对象的属性和方法统称为对象的成员
对象属性.和[]
1.1点方法后面跟的必须是一个指定的属性名称,而中括号方法里面可以是变量
var haha = "name";
console.log(obj.haha); // undefined
console.log(obj[haha]); // cedric
1.2中括号方法里面的属性名可以是数字,而点方法后面的属性名不可以是数字
2、判断对象是否包含某属性
2.1 in
// 使用格式
// prop in objectName
// prop:一个字符串类型或者 symbol 类型的属性名或者数组索引(非symbol类型将会强制转为字符串)。
// 检查它(或其原型链)是否包含具有指定名称的属性的对象。
var obj = {
name : 'fortune',
sex : 'monster'
}
'name' in obj; //true
'toString' in obj //true
'noExist' in obj //false
2.2 hasOwnProperty()
判断原型链上的属性是false,这就并不会判断非自身的属性了
hasObj.hasOwnProperty('name') //true
hasObj.hasOwnProperty('toString') //false
3、遍历对象属性
3.1 for in
for(var key in obj){
console.log(key);
}
3.2 Object.keys(xx)/Object.values(xx)
输出key的数组或values数组
[“name”, “career”]
3.3 Object.getOwnProperty
七、字符串出现次数的TopK问题
1、JS字典排序
数组.sort(function(a,b){
return a-b
})//return负数则不交换ab次序
2、JS中…的用法,将表达式展开
3、let m=new Map()
m.set(1,“black”)//添加一个新元素到映射
/**
* return topK string
* @param strings string字符串一维数组 strings
* @param k int整型 the k
* @return string字符串二维数组
*/
function topKstrings( strings , k ) {
// write code here
let obj={}
let res=[]
strings.sort()
//通过对象计数出现次数(也可以用map)
for(let i=0;i<strings.length;i++){
if(obj.hasOwnProperty(strings[i])){
obj[strings[i]]++;
}
else{
obj[strings[i]]=1
}
}
//字符串和次数存储为二维数组,方便下一步sort
for(var key in obj){
let arr2=[]
arr2.push(key,obj[key])
res.push(arr2)
}
//出现次数相同则字典升序,不同则降序列
res.sort(function(a,b){
if(a[1]==b[1]){
if(a[0]<b[0])return-1
else return 1
}
else{return b[1]-a[1]}
})
res.splice(k)
return res
}
module.exports = {
topKstrings : topKstrings
};
已积累的路长,当下所在点