二维数组在计算机中也是以连续空间存放,并记录第一行数组的索引位置,即 A[0][0]
的内存地址。
1.两个内部已排序数组,如arr1=[1,3,4,6,7],arr2=[3,4,6,8,9],将两个数组合并为一个新的排序数组。
思路:依次对比两个数组头部的数字,哪个小就放入新数组中,当其中一个已经空了,就把另一个剩余部分全追加到新数组后面。
$arr1=[1,3,4,5,9];
$arr2=[2,4,6,7,9];
function myMerge($arr1,$arr2){
$i=0;$j=0;
$int = array();
while($i<count($arr1) && $j<count($arr2)){
$int[] = $arr1[$i]<$arr2[$j]?$arr1[$i++]:$arr2[$j++];
}
while($i<count($arr1)){
$int[] = $arr1[$i++];
}
while($j<count($arr2)){
$int[] = $arr2[$j++];
}
return $int;
}
$a = myMerge($arr1,$arr2);
var_dump($a);
2.
思路:先算出数组值总和$sums,当判断中心点是否为0时,left_sum=0,右边就是$sums-$nums[0],
之后判断中心点是否为1,left_sum = left_sum+$nums[0],右边等于$sums-left_sum-$nums[1]
$nums = [1, 7, 3, 6, 5, 6];
function getCenter($nums){
$sums = array_sum($nums);
$left_sum = 0;
if($sums == $nums[0]){//总和等于$nums[0],那么剩下的元素和是0,此时0就是对称点
return 0;
}
for($i=1;$i<count($nums);$i++){
$left_sum += $nums[$i-1];
$right_sum = $sums - $left_sum - $nums[$i];
if($left_sum == $right_sum){//左边之和=右边之和
return $i;
}
}
return -1;
}
echo getCenter($nums);
3.
思路:
这题一开始是顺序对比,比nums[0]大就放它后面,小于等于它就放它前面
function searchInsert($nums, $target) {
for($i=0;$i<count($nums);$i++){
if($target <= $nums[$i]){
return $i;
}
}
return count($nums);
}
换一种思路,逆序对比,比最后一个数大就放它后面,如果遍历后不大于任意数,就直接拍首位
function searchInsert($nums, $target) {
for($i=count($nums)-1;$i>= 0 ;$i--){
if($nums[$i] < $target){
return $i+1;
}
}
return 0;
}
总体思路都是差不多的,看自己哪个边界值比较好理解就用哪个吧。
4.
思路:以为的水平,写不出不占用额外空间的写法,所以这是非常传统的赋值到新的数组,找到他们对应关系来旋转的:
function rotate(&$matrix) {
$count = count($matrix);
$count_i = count($matrix[0]);//因为所有一维数组长度相等
$arr = [];
for($i=0;$i<$count;$i++) {
for($j=0;$j<$count_i;$j++) {
$arr[$i][$j] = $matrix[$count - $j - 1][$i];
}
}
//$matrix = $arr; leetcode是要求最后给出$matrix的值所以才需要赋值一下
return $arr;
}
5.
思路:
1.找到0所在的行的集合$zero_a、列的集合$zero_b,这些都是要清零的。
2.遍历,当前行在$zero_a或者列在$zero_b,清零
为什么第一次找的时候不直接清零:怕污染原数组
(并不是特别高明的方法)
function setZeroes(&$matrix) {
$zero_a = $zero_b = [];
for($i=0;$i<count($matrix);$i++){
for($j=0;$j<count($matrix[$i]);$j++){
if($matrix[$i][$j] == 0){
if(! in_array($i,$zero_a)){
$zero_a[] = $i;//记录要清零的行
}
if(! in_array($j,$zero_b)){
$zero_b[] = $j;//记录要清零的列
}
}
}
}
for($i=0;$i<count($matrix);$i++){
for($j=0;$j<count($matrix[$i]);$j++){
if(in_array($i,$zero_a) || in_array($j,$zero_b)){ //当前行或列匹配到清零行或列
$matrix[$i][$j] = 0;
}
}
}
return $matrix;
}
6.快速排序
思路:先默认第一个是中间值,比它小的放它左边,比它大的放它右边,分别排序后,组合在一起。
function quick_sort($a){
$count = count($a);
if($count <= 1){
return $a;
}
$left = $right = [];
$mid = $a[0];
for($i=1;$i<$count ;$i++){
if($mid < $a[$i]){//升序< 降序> 其他不用改
$right[] = $a[$i];
}else{
$left[] = $a[$i];
}
}
$left = quick_sort($left);
$right = quick_sort($right);
return array_merge($left,array($mid),$right);
}
7.二分查找(注意是要对已排序数组才能用)
思路:先找到中间位置的数据,要查找的比它小,就去它左边找,比它大,就去它右边找。
function selectone($arr,$find,$left=0,$right=0){
if($right == 0){
$right = count($arr);
}
if($right < $left || $find>$arr[count($arr)-1] || $find < $arr[0]){
return 0;
}
if($right - $left<=1){
if($find==$arr[$right] || $find==$arr[$left]){
return 1;
}else{
return 0;
}
}
$mid=round(($left+$right)/2);
if($find > $arr[$mid]){
return selectone($arr,$find,$mid++,$right);
}elseif($find == $arr[$mid]){
return $mid;
}else{
return selectone($arr,$find,$left,$mid--);
}
}
8.冒泡排序
function selectone($arr){
for($i=0;$i<count($arr)-1;$i++){
for($j=0;$j<count($arr)-1-$i;$j++){
if($arr[$j] > $arr[$j+1] ){
$temp = $arr[$j];
$arr[$j] = $arr[$j+1];
$arr[$j+1] = $temp;
}
}
}
return $arr;
}
9.选择排序
function selectone($arr){
for($i=0;$i<count($arr)-1;$i++){
$min_index = $i;
for($j=$i;$j<count($arr)-1;$j++){
if($arr[$j+1] < $arr[$min_index] ){
$min_index = $j+1;
}
}
$temp = $arr[$i];
$arr[$i] = $arr[$min_index];
$arr[$min_index] = $temp;
}
return $arr;
}
10.
思路:这题需要位运算,
a ^ a = 0 任何一个数字和自己按位异或结果是0
a ^ 0 = a 任何一个数字和0按位异或结果是自己
(按位异或:按位取或后,再依次求反)
function singleNumber($nums) {
$single = 0;
foreach ($nums as $k => $v) {
$single= $single ^ $v;
}
return $single;
}
$nums = [4,1,2,1,2,4,6];
echo singleNumber($nums);
11.
思路:无论是否有地址,那地址肯定不能是主表了
select P.FirstName, P.LastName, a.City, a.State
from Person P
left join Address as a
on a.PersonId = p.PersonId
12.
思路:重复值 having
select Email from Person group by Email having count(Email) >1
13.
思路:递归
function fib($n) {
if($n<=1){
return $n;
}else{
return $this->fib($n-1)+$this->fib($n-2);
}
}
14.
思路:(效率不高)先遍历字符串,将所有出现过的字符串放入$map,所有$map中出现过的字符串放入$same,遍历原数组,返回不在$same的第一个。
function firstUniqChar($s) {
$arr = str_split($s);
$map = $same = [];
for($i=0;$i<count($arr);$i++){
if(! in_array($arr[$i], $map)){
$map[] = $arr[$i];
}else{
$same[]=$arr[$i];
}
}
for($i=0;$i<count($arr);$i++){
if(! in_array($arr[$i], $same)){
return $i;
}
}
return -1;
}
$s="always";
echo firstUniqChar($s);
另一种思路:(效率好一点点)先遍历,统一各个值出现的次数,再遍历,第一个使用一次的就是。(注意不要想着第一次遍历时存在的就设为1,再次出现就删除,这样出现三次的就会被当作一次了)
function firstUniqChar($s) {
$arr = str_split($s);
$map = [];
foreach ($arr as $k => $v) {
if(! isset($map[$v])){
$map[$v] = 1;
}else{
$map[$v] ++;
}
}
for($i=0;$i<count($arr);$i++){
if($map[$arr[$i]] == 1){
return $i;
}
}
return -1;
}
15.
思路:糖果种类可以遍历数组,记录在$map数组中,之后对比$map和糖果总数的一半,返回较小值。
function distributeCandies($candyType) {
$map = [];
foreach ($candyType as $k => $v) {
if(! in_array($v, $map)){
$map[] = $v;
}
}
return min(count($map),count($candyType)/2);
}
$candies = [1,1,2,2,2,2];
echo distributeCandies($candies);
16.
思路:id=1的员工ManagerID=3,意思是id=3的员工是他的经理。
我用的联表查询
select ee.Name as Employee from Employee as e join Employee as ee
on e.Id = ee.ManagerId
where ee.Salary > e.Salary
17.
18.