1.如何判断一个链表是否有环
经典解法是快慢指针,没有之一
typedef struct _Link{
Node *head;
int data;
} Link;
typedef struct _Node{
struct _Node *next;
int data;
}Node;
int checkCircle(Link *link){
Node *fast, *slow;
if(link->head == NULL)return 0;
fast = link->head;
slow = link->head;
while(1){
if(fast->next == NULL)return 0;
if(slow->next == NULL)return 0;
if(fast == slow)return 1;
fast = fast->next->next;
slow = slow->next;
}
}
2.反转一个链表
主要考察对单链表指针指向的先后顺序的操作,理论很简单,代码有点技巧
void reverseChain(Link *link){
Node *prev, *cur, *next;
if(link->head == NULL)return;
cur = link->head;
prev = NULL;
while(1){
if(cur == NULL)return;
next = cur->next;
cur->next = prev;
prev = cur;
cur = next;
}
}
3.判断括号字符串是否有效
主要考察对栈的使用,左括号入栈,只要发现右括号就出栈匹配,匹配不成功或者最后栈不空都说明字符串不合法
function isValid($str){
$stack = [];
$map = [')'=>'(', ']'=>'[', '}'=>'{'];
for($i=0; $i<strlen($str);$i++){
if(in_array($str[$i], $map))array_push($stack, $str[$i]);
if($map[$str[$i]]){
if(count($stack)==0)return false;
if(array_pop($stack) != $map[$str[$i]])return false;
}
}
return count($stack)==0;
}
4.用队列实现栈&用栈实现队列
function stack2queue(){
var input = [], output = [];
return {
push: function(v){
input.push(v);
},
pop: function(){
if(output.length>0)return output.pop();
while(input.length>0){
output.push(input.pop);
}
return output.pop();
},
length: function(){
return input.length + output.length;
}
}
}
5.返回数据流中的第K大元素
考察对堆排序的应用
#include <stdio.h>
void swap(int *arr, int i, int j){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
void printArr(int arr[], int len){
printf("==================================================================\n");
for (int i = 0; i < len; i++)
{
printf("%4d", arr[i]);
if (i != (len - 1))printf(",");
}
printf("\n==================================================================\n");
}
void HeapAdjust(int arr[], int p, int endIndex){
int i, tmp;
tmp = arr[p];
for (i = 2 * p + 1; i <= endIndex; i = i * 2 + 1){
if (i < endIndex && arr[i] < arr[i + 1])i++;
if (arr[p]>arr[i])break;
arr[p] = arr[i];
p = i;
}
arr[p] = tmp;
}
void HeapSort(int arr[], int endIndex){
int i;
for (i = endIndex / 2; i >= 0; i--){
HeapAdjust(arr, i, endIndex);
}
for (i = endIndex; i >= 0; i--){
swap(arr, 0, i);
HeapAdjust(arr, 0, i-1);
}
}
int *topK(int arr[], int len, int k){
int res[k], i;
for(i=0; i<len;i++){
if(i<k)res[i] = arr[i];
if(i>=k && res[k-1]<arr[i])res[k-1] = arr[i];
HeapSort(res, i);
}
return res[k-1];
}
6.返回滑动窗口中的最大值
function maxSlidingWindow($arr,$k){
$window = [];
$res = [];
if(empty($arr))return $res;
for($i=0;$i<count($arr);$i++){
if($i>=$k && $window[0]<=($i-$k))array_shift($window);
//以下可以保证$window是一个有序的递减数组,
while(count($window)>0 && $arr[$i]>=$window[count($window)-1]){
array_pop($window);
}
//$i不论大小都要入栈的,因为还不知道后面的数是大是小呢
array_push($window, $i);
if($i>=$k-1)array_push($res, $arr[$window[0]]);
}
return $res;
}
7.找出一个数组中有两数之和为k的组合
function twoSum($arr, $k){
$set = [];
$res = [];
foreach($arr as $key => $n){
$t = $k-$n;
if(in_array($t, $set)){
$res[] = [$t, $n];
}else{
array_push($set, $n);
}
}
return $res;
}
8.找出一个数组中三数之和为k的组合
function threeSum($arr, $k){
$set = [];
$res = [];
if(count($arr)<3)return $res;
foreach($arr as $ak=> $a){
foreach($arr as $bk=> $b){
if($bk<=$ak)continue;
$c = $k-$a-$b;
if($set[$c]){
$res[] = [$a, $b, $c];
}else{
$set[$a] = 1;
}
}
}
return $res;
}
9.判断一棵树是否是二叉排序树
int isValideNode(Node *root, Node *prev){
if(root == NULL)return 1;
if(isValidNode(root->left, prev)==0)return 0;
if(prev != NULL && prev->val > root->val)return 0;
prev = root;
return isValidNode(root->right, prev)
}
//第一种算法是用一个prev指针
int isValidBST(Node *root){
Node *prev = NULL;
return isValidNode(root, prev);
}
//第二种算法是用限定边界法
int isValidBST2(Node *root, Node *min, Node *max){
if(root == NULL)return 1;
if(min != NULL && root->val<min->val)return 0;
if(max != NULL && root->val>max->val)return 0;
return isValidBST2(root->left, min, root->val) &&
isValidBST2(root->right, root->val, max);
}
10.二叉搜索树的最近公共祖先
//以下针对普通的树
Node *findPOrQ(Node *root, Node *p, Node *q){
if(root == p || root == q || root == NULL)return root;
Node *left = findPOrQ(root->left, p, q);
Node *right = findPOrQ(root->right, p, q);
return left == NULL ?
right: (right == NULL? left: root);
}
//以下针对二叉搜索树
Node *findPOrQ2(Node *root, Node *p, Node *q){
if(p->val <root->val && root->val>q->val)
return findPOrQ(root->left, p, q);
if(p->val>root->val && root->val<q->val)
return findPOrQ(root->left, p, q);
return root;
}
//以下是针对搜索树的迭代实现
Node *findPOrQ3(Node *root, Node *p, Node *q){
while(root != NULL){
if(p->val<root->val && root->val>q->val)
root = root->left;
if(p->val>root->val && root->val<q->val)
root = root->right;
return root;
}
}
11.遍历二叉树
//先中后序遍历都是用递归最简单
void postOrder(Node *root){
if(root != NULL){
postOrder(root->left);
postOrder(root->right);
printf("%d", root->val);
}
}
12.求x的N次方:pow(x,n)
主要考察分治法
function newPow($x, $n){
if(!$n)return 1;
if($n<0)return 1/newPow($x, -$n);
if($n%2)return x*newPow($x, $n-1);
return newPow($x*$x, $n/2);
}
13.求众数:给出一个数组,找出其中出现次数最多的一个数
时间复杂度最小的是用map
function findMajority($arr){
$map = [], $max = 0, $maxNum = 0;
foreach($arr as $v){
if(!$map[$v])$map[$v] = 0;
$map[$v]++;
}
foreach($map as $n => $c){
if($c>$max){
$max = $c;
$maxNum = $n;
}
}
}
14.广度优先算法
def BFS(graph, start, end):
queue = []
queue.append([start])
visited.add(start)
while queue:
node = queue.pop()
visited.add(node)
process(node)
nodes = generate_related_nodes(node)
queue.push(nodes)
15.深度优先
visited = set();
def dfs(node, visited):
visited.add(node)
for next_node in node.children():
if not next_node in visited:
dfs(next_node, visited)
16.求二叉树的最大/小深度
int maxDepth(Node *node):
if not node:
return 0
return 1 + max(maxDepht(node.left), maxDepth(node.right))
int minDepth(Node *node):
if not node:
return 0
if not node.left:
return 0
if not node.right:
return 0
return 1 + min(minDepth(node.left), minDepth(node.right))
17.写一个函数,使其能生成所有可能的有效括号组合
function genParenthesis(n){
var res = [];
var gen = function(left, right, s){
if(left == n && right == n)return res.push(s);
if(left<n)gen(left+1, right, s+'(');
if(left>right && right<n)gen(left, right+1, s+')');
};
gen(0, 0, n, '');
return res;
}
18.二分查找
int binarySearch(int arr[],int len, int s){
int min=0, max=len-1, mid;
while(min<=max){
mid = (min+max)/2;
if(arr[mid]>s){
max = mid-1;
}else if(arr[mid]<s){
min = mid+1;
}else{
return mid;
}
}
return -1;
}
int binarySearch2(int arr[], int min, int max, int s){
int mid;
if(min<=max){
mid = (min+max)/2;
if(arr[mid]==s){
return mid;
}else if(arr[mid]>s){
return binarySearch2(arr, min, mid-1, s);
}else{
return binarySearch2(arr, mid+1, max, s);
}
}
return -1;
}