public class Node {
public int value;
public Node next;
}
public Node reverseList(Node head) {
Node pre = null;
Node next = null;
while (head != null) {
next = head.next;
head.next = pre;
pre = head;
head = head.next
}
return pre;
}
在等概率的情况下,顺序表插入一个结点需要平均移动n/2个结点。删除一个结点需要平均移动(n-1)/2个结点。具体的移动次数取决于长度n和位置i,两者越近,移动的越少。
非递归:
private int binarySearch(int[] arr, int searchKey) {
if (arr == null) {
return -1;
}
int n = arr.length;
int left = 0;
int right = n - 1;
while (left <= right) {
int mid = left + ((right -left) >> 1);
if (arr[mid] > searchKey) {
right = mid - 1;
} else if (arr[mid] < searchKey) {
left = mid + 1;
} else {
return mid;
}
}
return -1;
}
递归:
private int binarySearchRecursive(int[] arr, int left, int right) {
if (arr == null) {
return -1;
}
int n = arr.length;
int left = 0;
int right = n -1;
while (left <= right) {
int mid = left + ((right - left) >> 1);
if (arr[mid] > searchKey) {
binarySearchRecursive(arr, left, mid - 1);
} else if (arr[mid] < searchKey) {
binarySearchRecursive(arr, mid + 1, right);
} else {
return mid;
}
}
return -1;
}
需要注意的是,二分查找算法的时间复杂度为O(logn),最坏情况下的时间复杂度为O(logn)
private int getDepth(Node node) {
if (node == null) {
return 0;
}
int left = getDepth(node.left);
int right = getDepth(node.right);
return left > right ? (left + 1) : (right + 1);
}
其实我的想法是通过hashmap来实现,其实也没必要在乎数组是否是排序的。时间复杂度方面,遍历整个数组,将数组元素添加到hash中,最后再查询,时间复杂度应该是O(n).
function getTimes(arr, key) {
var n = arr.length;
var hash = {};
for (var i = 0; i < n; i ++) {
var ele = arr[i];
if (!hash[ele]) {
hash[ele] = 1;
} else {
hash[ele] ++;
}
}
if (hash[key]) {
return hash[key];
} else {
return -1;
}
}
private static void stasTimes(int[] arr, int key) {
int len = arr.length;
HashMap<Integer, Integer> hash = new HashMap<Integer, Integer>();
for (int i =0; i < len; i++) {
if (hash.containsKey(arr[i])) {
Integer val = hash.get(arr[i]) + 1;
hash.put(arr[i], val);
} else {
hash.put(arr[i], 1);
}
}
for (Integer hashKey: hash.keySet()) {
if (hashKey.intValue() == key) {
System.out.println(key + " has appeared " + hash.get(hashKey) + " times");
}
}
}
private char[] moveChar(String str, char a) {
char[] arr = str.toCharArray();
int i = arr.length - 1;
while (arr[i] != a) {
i --;
}
for (int j = i - 1; j >= 0; j --) {
if (arr[j] != a) {
arr[i] = arr[j];
arr[j] = a;
i --;
}
}
return arr;
}
冒泡排序
public static void bubbleSort(int[] arr) {
if (arr == null || arr.length == 0) {
return;
}
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j+1]]) {
swap(arr, j+1, j);
}
}
}
}
public static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
选择排序
##1.10 排序算法比较
排序算法 | 平均时间复杂度 | 最好情况 | 最坏情况 | 空间复杂度 | 稳定性 |
---|---|---|---|---|---|
冒泡排序 | O(n^2) | O(n) | O(n^2) | O(1) | 稳定 |
选择排序 | O(n^2) | O(n^2) | O(n^2) | O(1) | 不稳定 |
插入排序 | O(n^2) | O(n) | O(n^2) | O(1) | 稳定 |
希尔排序 | O(nlogn) | O(nlog^2n) | O(nlog^2n) | O(1) | 不稳定 |
归并排序 | O(nlog(n)) | O(nlogn) | O(nlogn) | O(n) | 稳定 |
快速排序 | O(nlogn) | O(nlogn) | O(n^2) | O(logn) | 不稳定 |
堆排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(1) | 不稳定 |
计数排序 | O(n+k) | O(n+k) | O(n+k) | O(k) | 稳定 |
桶排序 | O(n+k) | O(n+k) | O(n^2) | O(n+k) | 稳定 |
基数排序 | O(n*k) | O(n*k) | O(n*k) | O(n+k) | 稳定 |
. |
基本围绕简历聊,印象比较深的有几个问题
主要聊项目,技术聊的比较少,说一下印象深的问题
有印象的问题
项目经历为主,以及管理方面的问题,技术方面没聊,有印象的问题
感觉是专门准备了一些有深度的问题来问,有印象的有
1、关于ES6 Proxy (2019 今日头条)
2、你觉得TypeScript 和 JavaScript有什么区别
TypeScript中的 type 和 instance 区别
interface User {
name: string,
age: number
}
insterface SetUser {
(name: string, age: number) : void;
}
type SetUser = (name: string, age: number) => void;
// 都允许扩展
// interface extends type
type Name = {
name: string;
}
instance
// type 不是一个类型,它是类型别名
// type 可以声明基本类型别名,联合类型,元祖等类型
// 基本类型别名
type Name = string
// interface 可以 而type不行
// interface 能够声明合并
interface User {
name: string,
age: number
}
interface User {
sex: string
}
new Error 不会终止成员运行
async function f() {
console.log(1)
await new Promise((resolve, reject) => {
console.log(2)
throw new Error('出错了')
}).catch(err => {
console.log(3)
console.log('执行失败了')
})
console.log(4)
}
// 1234
使用 try-catch 的时候,会把容易引发异常的代码写到try 里面
async function f() {
try {
// await new Promise((resolve, reject) => {
// // throw new Error('出错了')
// resolve()
// })
await new Promise((resolve, reject) => {
throw new Error('出错了')
})
console.log('正常输出')
} catch (err) {
// 这里用来捕获异常
console.log('异常了)
}
}
async function Login () {
// 接口请求异常,
// 用户名错误、密码错误、用户不存在、500
// 前提条件: 接口把所有的异常都通过HTTp状态吗来返回
// 尤其是在使用axios 请求库的时候, 它会把所有超出200- 300范围的状态码捕获
try {
catch (err) {
}
}
}
注意
try {
const p = new Promise((resolve, reject) => {
throw new Error('error')
fs.readFile('./login.js', (err, data) => {
if (err) {
reject(err)
} else {
resolve(data)
}
})
})
// 这样可以捕获到
// p.then(data => {
// console.log(data)
// }).catch (err => {
// console.log('手动 调用catch 捕获异常')
// })
} catch (err) {
console.log('失败了')
}
// 没有错误