算法笔记(一)

算法笔记(一)
一、给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

说明:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

示例 1:
输入: [2,2,1]
输出: 1

示例 2:
输入: [4,1,2,1,2]
输出: 4
  这里用到了异或的思想,异或就是相同为0,不同为1。用二进制表示更为直观,例1 [2,2,1]转换为二进制就是[10,10,01],按位异或,10和10异或后得00,然后00与01异或,得01,即最终答案。如果使例2的情况依次异或可能手算有些慢,因异或有交换律,所以可以直接看成同数异或为0,得到答案4。代码如下:

public class Solution {
    public int SingleNumber(int[] nums) {
       int a=0;
        for(int i=0;i<nums.Length;i++){
            a^=nums[i];
        }
        return a;
    }     
}

二、给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。你可以假设数组是非空的,并且给定的数组总是存在众数。

示例 1:
输入: [3,2,3]
输出: 3

示例 2:
输入: [2,2,1,1,1,2,2]
输出: 2
  一开始的思路是先对数组排序,然后用两层for循环遍历数组,用count计数,count值最大的为众数,结果发现无法把count值和对应的数联系起来…
  然后看了别人的解题思路发现数学方法很简单,因为题目给定有众数,所以数组中间的那个数必然是众数。相应代码如下:

public class Solution {
    public int MajorityElement(int[] nums) {
       Array.Sort(nums);
        int a=nums.Length/2;
        return nums[a];
    }
}

注:/直接忽略小数,%取余(容易忘记),之前就是忘记了,用了Math.Floor向下取整结果报错了。
  
  然后学习了摩尔投票法,题中给定众数是在数组中出现次数大于 ⌊ n/2 ⌋ 的元素,大致思想可以概括为数组内不同元素两两抵消,因为众数大于 ⌊ n/2 ⌋ ,所以剩下来的那个数就是众数。

public class Solution {
    public int MajorityElement(int[] nums) {
       int i,num,count=1;
        num=nums[0];
        for(i=1;i<nums.Length;i++){ 
            if(count==0) num=nums[i];//count代表num出现的次数,若count==0(即当前num已被抵消,则将更换比较值)
            if(num==nums[i]) count++;
            else count--;
        }
        return num;
     }
}

三、搜索二维矩阵
  编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性:
每行的元素从左到右升序排列。
每列的元素从上到下升序排列。

示例:
现有矩阵 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。
给定 target = 20,返回 false。

思路:遍历数组每一行,对每一行执行二分查找。left为左指针,right为右指针,middle=(left+right)/2。若target==matrix[i,middle],则找到目标,返回true;若target>middle,则说明target位于middle右侧,因此把左指针移至middle右侧一位,即left=middle+1;若target<middle,则说明target位于middle左侧,同理把右指针移至middle左侧一位,即right=middle-1。执行以上操作的前提是left<=right。

代码如下:

public class Solution {
    public bool SearchMatrix(int[,] matrix, int target) {
        int i,left,right,middle;
        for(i=0;i<matrix.GetLength(0);i++){
            left=0;
            right=matrix.GetLength(1)-1;
            while(left<=right){
             middle=(left+right)/2;
             if(matrix[i,middle]==target) return true;
             else if(matrix[i,middle]<target) left=middle+1;
             else right=middle-1;
            }
         }
        return false;
     }
}

分治算法:
  思路是左下角的元素比它所在列的其他元素大,比它所在行的其他元素小,所以每次将target与左下角元素比较,就可以直接删去一行或者一列。代码如下:

public class Solution {
    public bool SearchMatrix(int[,] matrix, int target) {
        int i=matrix.GetLength(0)-1;
        int j=0;
        while(i>=0&&j<matrix.GetLength(1)){
            if(target==matrix[i,j]) return true;
            else if(target>matrix[i,j]) j++;
            else i--;
        }
        return false;
     }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值