week1题目记录

代码源OJ

101特殊的正方形

输入n,输出n行n列的由+.组成的正方形,其中最外面一圈全是+,第二圈全是.,…,对于第ii圈,如果ii是奇数,那么全是+,否则全是.

先赋值再输出, 根据圈数n, 进行n次赋值, 每次进行一层

赋完这一圈后,两个变量向中心收缩(l++,r–)

import java.util.Scanner;

public class main {
    public static void main(String[] args) {
        Scanner sc=new Scanner(System.in);
        char[][] f=new char[110][110];
        int n=sc.nextInt();
        int m=n;
        int up=0,l=0,r=n-1,down=n-1;
        char s[]={'+','.'};
        while(m>=0){
            char c=s[l%2];
            for (int i = 0; i < m; i++) {
                f[l+i][r]=c;
                f[l+i][l]=c;
                f[l][l+i]=c;
                f[r][l+i]=c;
            }
            l++;
            r--;
            m-=2;
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                System.out.print(f[i][j]);
            }
            System.out.println("");
        }
    }
}

102走楼梯2

楼梯有 n 阶,上楼可以一步上一阶,也可以一步上二阶。

但你不能连续三步都走两阶,计算走到第n阶共有多少种不同的走法

和正常的走楼梯问题不同点是不能连续走3次两阶,所以开一个N*3的二维数组

012标示三种状态(连续走了几次两阶)

f[1] [j]因为最后一步走的是2,所以就等于上上层的f[0] [j-2](因为最后一步是走了一次两步,所以只能通过上上层走一次两步得到,而因为最后一步只连续走了一次两步,所以只能通过f[0]得到,如果是f[1],最后一步再走一次两部就会变成f[2]),f[2] [j]因为最后一次走了两次两部,所以可以通过上上层的f[1] [j-2]得到(道理同上)

import java.util.Scanner;

public class main {
    public static void main(String[] args) {
        long[][] f=new long[3][110];
        Scanner sc=new Scanner(System.in);
        int n=sc.nextInt();
        f[0][0] = 1;
        f[0][1]=1;

        for (int i = 2; i <= n; i++) {
            f[0][i]=f[0][i - 1] + f[1][i - 1] + f[2][i - 1];
            f[1][i] = f[0][i - 2];
            f[2][i] = f[1][i - 2];
        }
        System.out.println(f[0][n] + f[1][n] + f[2][n]);

    }
}

103走路

有一条很长的数轴,一开始你在0的位置。接下来你要走n步,第i步你可以往右走ai或者bi。
问n步之后,0到m的每个位置,能不能走到

输出要求是走到最后一步之后, 可以走到的所有位置,如果最后一步走到了位置i,那么倒数第二步就需要走到i-a或者i-b,所以就考虑动态规划,用布尔数组来表示是否能走到i的位置,而每次转移就是考虑i-a或者i-b能不能走到,依次从后往前推到,这里的思路类似于走楼梯

import java.util.Scanner;
public class main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        boolean[][] st=new boolean[101][100001];
        int n=sc.nextInt();
        int m=sc.nextInt();

        for (int i = 1; i <=n ; i++) {
            int a=sc.nextInt();
            int b=sc.nextInt();
            for (int j = 0; j <=m ; j++) {
                if(st[i-1][j]==true&&j+a<=m) st[i][j+a]=true;
                if(st[i-1][j]==true&&j+b<=m) st[i][j+b]=true;
            }
        }
        for (int i = 0; i <=m ; i++) {//输出
            if(st[n][i]) System.out.print(1);
            else System.out.print(0);
        }
    }
}

哈希表学习

知识点总结:

一般哈希表都是用来快速判断一个元素是否出现集合里

牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据,实现快速的查找

常见的三种哈希结构
  • 数组
  • set (集合)
  • map(映射)

map 是一个key value 的数据结构,map中,对key是有限制,对value没有限制的,因为key的存储方式使用红黑树实现的

映射底层实现是否有序数值是否可以重复能否更改数值查询效率增删效率
std::map红黑树key有序key不可重复key不可修改O(log n)O(log n)
std::multimap红黑树key有序key可重复key不可修改O(log n)O(log n)
std::unordered_map哈希表key无序key不可重复key不可修改O(1)O(1)

例题1: 字母异位词

力扣242题

给定两个字符串 *s**t* ,编写一个函数来判断 *t* 是否是 *s* 的字母异位词。

**注意:**若 *s**t* 中每个字符出现的次数都相同,则称 *s**t* 互为字母异位词。

模板题, 因为只需要记录26个字母, 选择数组作为哈希结构, 记录s中每个字母的出现次数, 与t进行比较

class Solution {
    public boolean isAnagram(String s, String t) {
        int[] record=new int[26];
        
        for(int i=0;i<s.length();i++){
            record[s.charAt(i)-'a']+=1;
        }
        for(int i=0;i<t.length();i++){
            record[t.charAt(i)-'a']-=1;
        }
        for(int count:record){
            if(count!=0) return false;
        }
        return true;

    }
}

例题2: 两个数字的交集

力扣349题

给定两个数组 nums1nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一

set的使用, 先将sum1的数字放入set , 在遍历2的过程中判断哈希表中是否存在该元素

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
            if(nums1==null||nums1.length==0||nums2==null||nums2.length==0){
                return new int[0];
            }
            Set<Integer> set1=new HashSet<>();
            Set<Integer> resSet=new HashSet<>();

            for(int i:nums1) set1.add(i);
            for(int i:nums2) if(set1.contains(i)) resSet.add(i);
            //return resSet.stream().mapToInt(x -> x).toArray();

            int[] arr=new int[resSet.size()];
            int j=0;
            for(int i:resSet)
            {
                arr[j++]=i;
            }
            return arr;
    }
}

例题3: 两数之和

力扣1题

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

因为有两个重要元素(值, 下标), 所以选择map;

for遍历, 看map中有没有与当前元素配对的元素, 若有,加入res数组,若无, 加入map

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] res=new int[2];
        Map<Integer, Integer>map=new HashMap<>();
        for(int i=0;i<nums.length;i++){
            int temp=target-nums[i];
            if(map.containsKey(temp)){
                res[1]=i;
                res[0]=map.get(temp);
                break;
            }
            map.put(nums[i],i);
        }
        return res;
    }
}

例题4: 四数相加

力扣454题

给你四个整数数组 nums1nums2nums3nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:

  • 0 <= i, j, k, l < n
  • nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
  1. 首先定义 一个map,key放a和b两数之和,value 放a和b两数之和出现的次数
  2. 遍历A和B数组,统计两个数组元素之和,和出现的次数,放到map中
  3. 定义int变量count,用来统计 a+b+c+d = 0 出现的次数。
  4. 在遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。(res+=map.get(0-temp))
  5. 最后返回统计值 count 就可以了
class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        Map<Integer,Integer> map=new HashMap<>();
        int temp;
        int res=0;
        for(int i:nums1){
            for(int j:nums2){
                temp=i+j;
                if(map.containsKey(temp)){
                    map.put(temp,map.get(temp)+1);
                }else{
                    map.put(temp,1);
                }
            }
        }
        for(int i:nums3){
            for(int j:nums4){
                temp=i+j;
                if(map.containsKey(0-temp)){
                    res+=map.get(0-temp);
                }
            }
        }
        return res;
    }
}

例题5: 四数相加

力扣383赎金信

给你两个字符串:ransomNotemagazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。

如果可以,返回 true ;否则返回 false

magazine 中的每个字符只能在 ransomNote 中使用一次。

标记magazine中出现的字母, 再遍历ransomNote, 需全部包含才可以(不用管次数)

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        int[] record=new int[26];
        for(char c:magazine.toCharArray()){
            record[c-'a']++;
        }
        for(char c:ransomNote.toCharArray()){
            record[c-'a']--;
        }
        for(int i:record){
            if(i<0) return false;
        }
        return true;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值