leetcode1

1.二叉树平均值

大概题目意思:记录二叉树每一层的平均值
解法:采用队列,每次先获取队列中的点个数,然后遍历这几个点,记录值,并且将每个点的左右结点(如果有)入队,这样就完成了一层的纪录,队列为空后,记录完毕。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    vector<double> averageOfLevels(TreeNode* root) {
      queue<TreeNode*> que;
      vector<double> ans;
      que.push(root);
      int size;
      double sum=0;
      TreeNode* node;
      
    while(!que.empty()){
    size=que.size();
    for(int i=1;i<=size;i++){
        node=que.front();
        que.pop();
        sum+=node->val;
        if(node->left!=NULL)que.push(node->left);
        if(node->right!=NULL)que.push(node->right);
    }
    ans.push_back(sum/size);
    sum=0;


    }

      

      return ans;
    }
};

2.多少小于当前数字的数字

在这里插入图片描述
思路1:暴力枚举,时间n2
思路2:二维数组,一重记录值,一重记录原数组的顺序,然后sort,sort完设置一个pre指针遍历,pre的值就是答案,时间nlog2n

class Solution {
    public int[] smallerNumbersThanCurrent(int[] nums) {
        int n=nums.length;
        int pre=-1;
        int []res=new int [n];
        int [][]set=new int[n][2];
        for(int i=0;i<n;i++)
        {
            set[i][0]=nums[i];
            set[i][1]=i;
        }
        Arrays.sort(set, new Comparator<int []>(){
            public int compare(int data1[],int data2[]){
                return data1[0]>data2[0]?1:-1;
            }
        });
        
       
        for(int i=0;i<n;i++){
            if(pre==-1||set[i][0]!=set[i-1][0])
            pre=i;
            res[set[i][1]]=pre;
        }

        return res;
    }
}

思路3:计数排序,然后一个for循环叠加起来,此时数组里的前一个位置的值就是答案,注意当原数组中如果有0的数据,此时必须加一个特判,否则越界

class Solution {
    public int[] smallerNumbersThanCurrent(int[] nums) {
        int n = nums.length;
        int [] cnt = new int [101];
        int [] res = new int [n];
        for(int i=0;i<n;i++)
        cnt[nums[i]]++;
        
        for(int i=1;i<101;i++)
        cnt[i]+=cnt[i-1];

        for(int i=0;i<n;i++)
        res[i]=nums[i]==0?0:cnt[nums[i]-1];
        return res;
    }
}

3.二叉树先序遍历在这里插入图片描述

思路1:递归,注意这里List是接口

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> List =new ArrayList<Integer>();
        dfs(root,List);
        return List;
    }
    public void dfs(TreeNode root,List List){
        if(root==null)return;
        List.add(root.val);
        dfs(root.left,List);
        dfs(root.right,List);
    }
}

思路2:栈。每次拿到一个节点,先取值然后向左边迭代直至为空,之后弹出取右边。拿到右边也是重复向左迭代直至为空的操作

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> List =new ArrayList<Integer>();
        Stack<TreeNode>stack = new Stack<TreeNode>();
        TreeNode t;
        if(root==null)return List;
        t=root;

        while(!stack.empty()||t!=null){
            while(t!=null){
                List.add(t.val);
                stack.push(t);
                t=t.left;
            }

            t=stack.pop();
            t=t.right;

        }
        return List;
    }
}

4.每个数字出现的次数是否独一无二

在这里插入图片描述
思路 :用map记录个数,然后遍历map把value加入set,然后比较长度
注意:set或者map读取长度用的size是一个函数,需要加(),并非数组直接length

class Solution {
    public boolean uniqueOccurrences(int[] arr) {
        Map<Integer,Integer> map= new HashMap<Integer,Integer>();
        for(int i : arr)
        map.put(i,map.getOrDefault(i,0)+1);

        Set<Integer>set = new HashSet<Integer>();
        
        for(Map.Entry<Integer,Integer> entry : map.entrySet())
        set.add(entry.getValue());
        
        return set.size()==map.size();
    }
}

5.求根到叶子节点的数字之和

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int sumNumbers(TreeNode root) {
        return dfs(root,0);
    }
    int dfs(TreeNode root,int val){
        if(root==null)return 0;
        val=val*10+root.val;
        if(root.left==null&&root.right==null)return val;
        else return dfs(root.left,val)+dfs(root.right,val);
    }
}

6.岛屿的周长

在这里插入图片描述
思路1:遍历每一个点,然后遍历它的四个方向的点,如果越界或者为水,则ans++

class Solution {
    public int islandPerimeter(int[][] grid) {
        int[] dx={-1,1,0,0};
        int[] dy={0,0,1,-1};
        int n=grid.length;
        int m=grid[0].length;
        int ans=0;
        int x1,y1;
        for(int i=0;i<n;i++)
        for(int j=0;j<m;j++){
            if(grid[i][j]==1)
            for(int k=0;k<4;k++){
                x1=i+dx[k];
                y1=j+dy[k];
                if(x1<0||y1<0||x1>=n||y1>=m||grid[x1][y1]==0)ans+=1;//一条边如果被算进来,这条边不会再被重复计
            }
        }
        return ans;
    }
}

思路2:dfs

class Solution {
        int[] dx={-1,1,0,0};
        int[] dy={0,0,1,-1};
    public int islandPerimeter(int[][] grid) {
        int n=grid.length;
        int m=grid[0].length;
        int ans=0;
        for(int i=0;i<n;i++)
        for(int j=0;j<m;j++){
            if(grid[i][j]==1)
            ans+=dfs(i,j,grid,n,m);
        }
        return ans;
    }
    int dfs(int x,int y,int[][]grid,int n,int m){
        int ret=0;
        if(x<0||y<0||x>=n||y>=m||grid[x][y]==0)return 1;
        if(grid[x][y]==2)return 0;//放前面可能会数组越界
        grid[x][y]=2;
        int x1,y1;
        for(int k=0;k<4;k++){
            x1=x+dx[k];
            y1=y+dy[k];
            ret+=dfs(x1,y1,grid,n,m);
        }
        
        return ret;
    }
}



2021/3/4

7.反转链表

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode*p=head;
        ListNode* temp=NULL;
        ListNode* tail=NULL;
        while(p!=NULL){
            temp=new ListNode(p->val);
            temp->next=tail;
            tail=temp;
            p=p->next;
        }
        return tail;
    }
};

思路1(自己做法):遍历链表,然后每遇到一个节点都进行new,把该新节点指向tail,并且不断更新tail,需要耗费内存

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode*p=head;
        ListNode* nextTemp=NULL;
        ListNode* preTemp=NULL;
        while(p!=NULL){
            nextTemp=p->next;
            p->next=preTemp;
            preTemp=p;
            p=nextTemp;
        }
        return preTemp;
    }
};

思路2 遍历每一个节点的时候记录更新前一个节点和后一个节点,然后改next即可,可以不耗费内存

8.两数之和

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        map<int,int> ma;
        for(int i=0;i<nums.size();i++)
            ma[nums[i]]=i+1;
        for(int i=0;i<nums.size();i++){
            if(ma[target-nums[i]]&&ma[target-nums[i]]!=i+1)
            return {i,ma[target-nums[i]]-1};
        }
        return {};

    }
};

思路 这题卡了好久,首先我一开始没有判断遍历时候的对应点是否是原点(题目数组中有重复元素),然后这个问题可以通过记录下标来解决。也可以一遍哈希,先找对应点再存储当前点,因为如果答案存在,这个点是会被再度遍历的。

9.剪绳子

在这里插入图片描述
思路1:数学,用数学方法证明当每段的长度为3的时候,结果最大。然后根据余数和商返回结果

class Solution {
public:
    int cuttingRope(int n) {
        if(n<=3)return n-1;//n为3必须特判,因为题目要求绳子必须剪
        int a=n/3;
        int b=n%3;
        if(b==0)return pow(3,a);
        else if(b==1)return pow(3,a-1)*4;
        else return pow(3,a)*2;
    }
};

思路2:动态规划,dp[i]代表长度为i的绳子经过剪去处理后能够得到的最好结果,可以获得dp方程:
for j 2 to i-2 //两段必须长度都大于2才有意义
dp[i]=max(dp[i],max(j*(i-j),j*dp[i-j]))
注意j的范围,还是让它可以等于i,否则当n=3的时候循环进不去

class Solution {
public:
    int dp[202]={0};
    int cuttingRope(int n) {
        dp[2]=1;
        for(int i=3;i<=n;i++){
            for(int j=2;j<=i;j++){
                dp[i]=max(dp[i],max(j*(i-j),j*dp[i-j]));
            }
        }
        return dp[n];
    }
};

10.二叉树是否对称

对于每一对对称的节点,
1.L=R
2.LL=RR
3.LR=RL

class Solution {
public:
    bool isMirror(TreeNode*L,TreeNode*R){
        if(L==NULL&&R==NULL)return true;
        else if(L==NULL||R==NULL||L->val!=R->val)return false;
        return isMirror(L->left,R->right)&&isMirror(L->right,R->left);

    }
    bool isSymmetric(TreeNode* root) {
        if(root==NULL)return true;
        return isMirror(root->left,root->right);
    }
};

11.判断后序遍历序列是否为二叉搜索树

后序遍历这一块还是好说,主要是判断二叉搜索树这里卡住了。在找到mid节点之后,继续利用这个mid节点,如果他能走到相应位置,则为二叉搜索树,否则错误。判断的时候可以往根节点地方走会简便一些,我这里刚好是反方向

class Solution {
public:
    bool dfs(vector<int>& postorder,int left, int right){
        if(left>=right)return true;//大于的情况是有单个孩子的情况,模拟一下可知
        int mid=right;
        while(mid>=left&&postorder[mid]>=postorder[right])mid--;
        int tempmid=mid;
        while(tempmid>=left&&postorder[tempmid]<postorder[right])tempmid--;//如果是二叉搜索树,该指针最后会比left小1
        return left-tempmid==1&&dfs(postorder,left,mid)&&dfs(postorder,mid+1,right-1);
    }
    bool verifyPostorder(vector<int>& postorder) {
        return dfs(postorder,0,postorder.size()-1);
    }
};

12.最长不含重复字符子字符串

思路: 双指针+哈希映射定位左指针
让右指针一直往右边移动,当出现出现的字符在map中时候(可能不在当前区间,这个用max处理),让i定位到记录的字符之后一位

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int i=0,j=0;
        int ans=0;
        map<char,int> M;
        while(j<s.size()){
            if(M.find(s[j])!=M.end()){
                i=max(i,M[s[j]]+1);//这里用max是因为可能M中的这个s[j]并不在区间内
            }
            M[s[j]]=j;
            ans=max(ans,j-i+1);
            j++;
        }
        return ans;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值