一、题号1232:点缀成线
1.1 思路分析:
1、判断给定坐标值组成的数组中的元素是否在一条直线上。首先想到到可以是通过斜率来进行判断。
2、通过斜率来进行判断就不可避免的用到了除法,在计算机运算中,除法所耗费的资源比乘法多很多,而且有可能因为截断精度的问题造成问题。除此之外,需要注意到与X轴垂直时如何进行判断是否位于一条直线上,因此不太建议使用除法,虽然本例可以使用此种方式达到提交通过的目的。
3、解法二是使用到了线性代数中的二维向量如果线性相关的时候,则其共线,且所拼接的二阶矩阵的行列式值为0.
1.2 解法一:通过斜率计算来判断的解法如下所示:
var checkStraightLine = function(coordinates) {
//1、判断给定坐标点组成的数组中的元素是否在同一条直线上
//先判断特殊情况,如果数组的长度不大于2,则显然在一条直线上了。
if(coordinates.length<=2) return true;
//给定的长度大于2时,则直线的斜率可以计算出来
if(coordinates[0][0]===coordinates[1][0]){
for(let i=1;i<coordinates.length;i++){
if(coordinates[i][0]!==coordinates[0][0]){
return false;
}
}
return true;
}
//已经排除了与X轴相垂直的情况,可以进行斜率的计算了
let k=(coordinates[1][1]-coordinates[0][1])/(coordinates[1][0]-coordinates[0][0]);
//则后面任意的一个点与第一个点的斜率都应该与k值相等
for(let i=2;i<coordinates.length;i++){
let m=(coordinates[i][1]-coordinates[0][1])/(coordinates[i][0]-coordinates[0][0]);
if(m!==k) return false;
}
return true;
};
此种解法的性能如下:
1.3 解法二:使用线性代数中线性相关的概念进行简化代码量
解法如下:
var checkStraightLine = function(coordinates) {
//使用线性代数相关的知识,二维的向量共线则其拼接而成的矩阵的行列式值为0
let m=coordinates.length;
let x0=coordinates[0][0];
let y0=coordinates[0][1];
//通过第一个点和第二点计算出第一个向量的指向
let x=coordinates[1][0]-x0;
let y=coordinates[1][1]-y0;
for(let i=2;i<m;i++){
let xi=coordinates[i][0]-x0;
let yi=coordinates[i][1]-y0;
if(x*yi-xi*y!==0) return false;
}
return true;
};
此种解法性能如下所示:
总结分析:可以看出来其实上述两种解法的性能上都差不多,但是第二种方式的解法更加科学,可以避免因为输入集的改变导致的测试不通过现象,同时代码量也相对较少,逻辑也更加清晰明了。
二、题号496 下一个数更大
2.1 思路分析
1、nums1中的数组是nums2的子数组,因此其长度不可能超过nums2,需要注意到的是,两个数组相同元素的索引值并不一样,根据题意,应该很清楚首先我们需要找到与nums1中相同元素值在nums2中的索引值,第二步进一步进行循环迭代判断其大于其索引值的部分有没有比当前索引值更大的元素,有则返回其值,否则返回的是-1.
2、此处的关键在于如何通过循环语句找到1是满足nums1与·nums2相同元素的索引值,2是如何在其nums2查找到的元素值的右侧找到下一个更大元素的值,当循环的次数不确定的时候,我们可以使用到while循环,根据题意设定合适的循环判入条件即可。
3、创建用于返回的数组和对此数组进行插入元素操作时,我们可以使用到Array的构造函数创建指定长度的数组,以及使用res[i]==?的按位填充的方式。
2.2 解法一如下:
var nextGreaterElement = function(nums1, nums2) {
let m=nums1.length;
let n=nums2.length;
//使用内置对象Array中所提供的构造函数创建并使用0进行数组的填充
let res=new Array(m).fill(0);
for(let i=0;i<nums1.length;i++){
let j=0;
while(j<n&&nums1[i]!==nums2[j]){
j++;
}
//上述循环中找到了两个数组中相等元素的值
//对于nums中继续循环找出下一个大于相等元素的值
let k=j+1;
while(k<n&&nums2[k]<nums2[j]){
k++;
}
//直接使用按位填充比使用数组的添加元素方法更有效。
res[i]=k<n?nums2[k]:-1;
}
return res;
};
此种解法的性能如下:
三、 题号589:N叉树的前序遍历
3.1 思路分析
此题直接使用递归法非常简单,按照N叉树的前序遍历的概念即可解出。关于N叉树的遍历补充一些东西如下所示:
N叉树的定义:二叉树中每个结点有一个数据项,最多有两个子节点,如果允许树的每个节点可以有两个以上的子节点,那么这个树就称为n阶的多叉树,或者称为n叉树
N叉树的前序遍历、后序遍历以及层级遍历的概念和方式。
3.2 解法一:递归法解题
代码如下:
var preorder = function(root) {
//先明白N叉树和二叉树的前序和先序遍历之间的区别
let res=[];
helper(root,res);
return res;
}
const helper=function(root,res){
if(root===null){
return ;
}
res.push(root.val);
for(const ch of root.children){
helper(ch,res);
}
}
此种解法性能如下: