NC86 矩阵元素查找
描述
已知一个有序矩阵mat,同时给定矩阵的大小n和m以及需要查找的元素x,且矩阵的行和列都是从小到大有序的。设计查找算法返回所查找元素的二元数组,代表该元素的行号和列号(均从零开始)。保证元素互异。
数据范围:0 \le n,m \le 10000≤n,m≤1000,矩阵中的任何元素满足 0 < mat_{i,j} \le 10000000<mat**i,j≤1000000
要求:空间复杂度 O(1)O(1),时间复杂度 O(n+m)O(n+m)
示例1
输入:
[[1,2,3],[4,5,6]],2,3,6
返回值:
[1,2]
示例2
输入:
[[1,2,3]],1,3,2
返回值:
[0,1]
方法一:
/**
*
* @param mat int整型二维数组
* @param n int整型
* @param m int整型
* @param x int整型
* @return int整型一维数组
*/
function findElement( mat , n , m , x ) {
// 方法一(暴力)
let res=[]
for(let i=0;i<n;i++){
for(let j=0;j<m;j++){
if(mat[i][j]==x){
res.push(i);
res.push(j);
}
}
}
return res;
}
module.exports = {
findElement : findElement
};
方法二:
function findElement( mat , n , m , x ) {
// 方法二(贪心)
// 定位左下角
let i=n-1,j=0;
// 当坐标在矩阵内部时一直循环
while(i>=0&&j<m){
// 往上走
if(mat[i][j]>x){
i--;
// 往右走
}else if(mat[i][j]<x){
j++;
// 找到值退出
}else{
break;
}
}
return [i,j];
}
module.exports = {
findElement : findElement
};
NC26 括号生成
描述
给出n对括号,请编写一个函数来生成所有的由n对括号组成的合法组合。
例如,给出n=3,解集为:
“((()))”, “(()())”, “(())()”, “()()()”, “()(())”
数据范围:0 \le n \le 100≤n≤10
要求:空间复杂度 O(n)O(n),时间复杂度 O(2^n)O(2n)
示例1
输入:
1
返回值:
["()"]
示例2
输入:
2
返回值:
["(())","()()"]
代码:
/**
*
* @param n int整型
* @return string字符串一维数组
*/
function generateParenthesis( n ) {
let res=[];
function find(left,right,str){
// 当左括号和右括号的数目都等于n时
if(left==n&&right==n){
return res.push(str);
}
// 使用左括号
if(left<n){
find(left+1,right,str+"(")
}
// 当右括号少于左括号时,使用右括号
if(right<n&&right<left){
find(left,right+1,str+")")
}
}
find(0,0,"");
return res;
}
module.exports = {
generateParenthesis : generateParenthesis
};
NC2 重排链表
描述
将给定的单链表\ L L: L_0→L_1→…→L_{n-1}→L_ nL0→L1→…→L**n−1→L**n
重新排序为:L_0→L_n →L_1→L_{n-1}→L_2→L_{n-2}→…L0→L**n→L1→L**n−1→L2→L**n−2→…
要求使用原地算法,不能只改变节点内部的值,需要对实际的节点进行交换。
数据范围:链表长度 0 \le n \le 200000≤n≤20000 ,链表中每个节点的值满足 0 \le val \le 10000≤val≤1000
要求:空间复杂度 O(n)O(n) 并在链表上进行操作而不新建链表,时间复杂度 O(n)O(n)
进阶:空间复杂度 O(1)O(1) , 时间复杂度 O(n)O(n)
示例1
输入:
{1,2,3,4}
返回值:
{1,4,2,3}
说明:
给定head链表1->2->3->4, 重新排列为 1->4->2->3,会取head链表里面的值打印输出
示例2
输入:
{1,2,3,4,5}
返回值:
{1,5,2,4,3}
说明:
给定head链表1->2->3->4->5, 重新排列为 1->5>2->4->3,会取head链表里面的值打印输出
示例3
输入:
{}
返回值:
{}
代码:
/*
* function ListNode(x){
* this.val = x;
* this.next = null;
* }
*/
/**
*
* @param head ListNode类
* @return void
*/
function reorderList( head ) {
// 方法一
// 如果链表为空或者只有一个值返回空
if(head==null||head.next==null){
return head
}
// p用于遍历链表
let p=head;
// p2用于存储链表后半部分的值
let p2=[];
let count=0,sum=0;
// 计算链表长度
while(p){
p2.push(p.val)
p=p.next;
count++;
}
p=head;
sum=0;
// 截取前半部分链表
while(sum<count/2-1){
p=p.next;
sum++;
}
p.next=null;
// 在前半部分链表中间隔插入p2弹出的节点
p=head;
let cur;
let node;
for(let i=1;i<=count/2;i++){
// node新建一个节点存储p2尾部弹出的值
node=new ListNode(p2.pop());
// 保存p后半部分的值
cur=p.next;
// 在head中插入新节点
p.next=node;
// 让head重新指向暂存在cur的后半部分
p.next.next=cur;
// 让p后移两个节点
p=p.next.next;
}
return head;
}
module.exports = {
reorderList : reorderList
};
NC42 有重复项数字的全排列
描述
给出一组可能包含重复项的数字,返回该组数字的所有排列。结果以字典序升序排列。
数据范围: 0 < n \le 80<n≤8 ,数组中的值满足 -1 \le val \le 5−1≤val≤5
要求:空间复杂度 O(n!)O(n!),时间复杂度 O(n!)O(n!)
示例1
输入:
[1,1,2]
返回值:
[[1,1,2],[1,2,1],[2,1,1]]
示例2
输入:
[0,1]
返回值:
[[0,1],[1,0]]
代码:
/**
*
* @param num int整型一维数组
* @return int整型二维数组
*/
function permuteUnique( num ) {
// write code here
let res=[];
let path=[];
let vis=new Array(num.length).fill(false);
num.sort((a,b)=>{
return a-b;
})
function dfs(curr,vis){
// 临时数组加满,存入res
if(curr.length==num.length){
res.push([...curr]);
return;
}
for(let i=0;i<num.length;i++){
// 如果当前元素与同一层的前一个相同并且num[i-1]已经使用过了
if(num[i]==num[i-1]&&!vis[i-1])
continue;
// 如果当前元素未被加入
if(!vis[i]){
// 加入当前元素
curr.push(num[i]);
// 标记当前元素被加入
vis[i]=true;
// 递归
dfs(curr,vis);
// 回溯
curr.pop();
// 标记弹出元素未被加入
vis[i]=false;
}
}
}
dfs([],vis);
// res里的路径去重
// let obj={}
// res.forEach(item=>obj[item]=item)
// res=Object.values(obj);
return res
}
module.exports = {
permuteUnique : permuteUnique
};
NC46 加起来和为目标值的组合(二)
描述
给出一组候选数 c 和一个目标数 t ,找出候选数中起来和等于 t 的所有组合。
c 中的每个数字在一个组合中只能使用一次。
注意:
\1. 题目中所有的数字(包括目标数 t )都是正整数
\2. 组合中的数字 ( a_1, a_2, … , a_ka1,a2,…,a**k ) 要按非递减排序 ( a_1 \leq a_2 \leq … \leq a_ka1≤a2≤…≤a**k ).
\3. 结果中不能包含重复的组合
\4. 组合之间的排序按照索引从小到大依次比较,小的排在前面,如果索引相同的情况下数值相同,则比较下一个索引。
数据范围: 1 \le n \le 701≤n≤70 ,1 \le target \le 1001≤targe**t≤100 , 1 \le C_i \le 501≤C**i≤50
要求:空间复杂度 O(n)O(n) , 时间复杂度 O(2^n)O(2n)
示例1
输入:
[100,10,20,70,60,10,50],80
返回值:
[[10,10,60],[10,20,50],[10,70],[20,60]]
说明:
给定的候选数集是[100,10,20,70,60,10,50],目标数是80
示例2
输入:
[2],1
返回值:
[]
代码:
/**
*
* @param num int整型一维数组
* @param target int整型
* @return int整型二维数组
*/
function combinationSum2( num,target) {
let res=[];
let vis=new Array(num.length).fill(false);
// 对数组排序
num.sort((a,b)=> a-b)
// 深度搜索
function dfs(ans,target,begin ){
// 如果当前值为0,则将答案存入res中
if(target==0){
res.push([...ans]);
}
// 当当前值小于0则退出
if(target<0){
return ;
}
// 从begin开始遍历数组
for(let i=begin;i<num.length;i++){
// 如果当前值与前一个值相同并且当前值大于起始值
if(num[i]==num[i-1]&&i>begin){
continue;
}
ans.push(num[i]);
// 从下一个位置开始递归
dfs(ans,target-num[i],i+1);
// 恢复数组
ans.pop();
}
}
dfs([],target,0)
return res;
}
module.exports = {
combinationSum2 : combinationSum2
};