547.朋友圈
题解:典型的并查集模板题 初始化每个人都有一个朋友圈 所以初始化朋友圈为人数个数 当给出i和j是朋友时 分别先搜i和j最头上的人 不一样则让一方指向另一方 同时朋友圈数目减1
不废话了,直接上代码了
class Solution {
int [] p = new int[201];
int result;
public int findCircleNum(int[][] M) {
result = M.length;
init(M.length);
for(int i=0;i<M.length;i++){
for(int j=0;j<M.length;j++){
if(M[i][j]==1){
unionset(i,j);
}
}
}
return result;
}
private void unionset(int x, int y) {
int xx = Find(x);
int yy = Find(y);
if(xx!=yy){
p[yy]=xx;
result--;
}
}
private int Find(int x) {
if(x!=p[x]){
p[x]=Find(p[x]);//状态压缩
}
return p[x];
}
private void init(int length) {
for(int i=0;i<length;i++){
p[i]=i;
}
}
}
448.找到所有数组中消失的数字
题解:标记法 先循环遍历一遍把出现的数字进行标记 再循环遍历没有出现的数字添加到集合中
不废话了,直接上代码了
class Solution {
public List<Integer> findDisappearedNumbers(int[] nums) {
List<Integer> list = new ArrayList<Integer>();
boolean [] flags = new boolean[nums.length+1];
for(int i=0;i<nums.length;i++){
flags[nums[i]]=true;
}
for(int i=1;i<=nums.length;i++){
if(flags[i]==false){
list.add(i);
}
}
return list;
}
}
682.棒球比赛
题解:因为C是去掉分数 所以你不能简单的用几个变量来保存 所以要用到数组 因为是动态的 所以我就直接上集合了
public int calPoints(String[] ops) {
int finalscore=0;
List<Integer> list = new ArrayList<Integer>();
for(int i=0;i<ops.length;i++){
if(ops[i].charAt(0)=='C'){
int score = list.get(list.size()-1);
finalscore-=score;
list.remove(list.size()-1);
}
else if(ops[i].charAt(0)=='D'){
int score = list.get(list.size()-1)*2;
list.add(score);
finalscore+=score;
}
else if(ops[i].charAt(0)=='+'){
int score = list.get(list.size()-1)+list.get(list.size()-2);
list.add(score);
finalscore+=score;
}
else{//第一次我还智障的写了下判断数字。。。后边看了那些排名前边的代码发现压根不需要
int score = Integer.valueOf(ops[i]);
finalscore+=score;
list.add(score);
}
}
return finalscore;
}
557.反转字符串中的单词 III
题解:用空格分割,之后循环对每个单词进行反转
class Solution {
public String reverseWords(String s) {
String [] strs = s.split(" ");
StringBuilder sb = new StringBuilder();
for(int i=0;i<strs.length;i++){
sb.append(new StringBuilder(strs[i]).reverse().toString()+(i==strs.length-1?"":" "));
}
return sb.toString();
}
}
942.增减字符串匹配
题解:因为I是增 D是减 范围是从0-length 所以增可以从0开始 减则从length开始 要从中知道并了解到分治的思想
class Solution {
public int[] diStringMatch(String S) {
int [] results = new int[S.length()+1];
int min = 0;
int max = S.length();
for(int i=0;i<S.length();i++){
if(S.charAt(i)=='I'){
results[i]=min++;
}else{
results[i]=max--;
}
}
results[S.length()]=max;//最后无论添加max还是min都是一样的 因为两个值相同了
return results;
}
}
852.山脉数组的峰顶索引
题解:注意题目 不要想太多了 直接找第一个该数大于后边的数 记录下其索引就OK了
class Solution {
public int peakIndexInMountainArray(int[] A) {
int result=-1;
for(int i=1;i<A.length-1;i++){
if(A[i]>A[i+1]){
result = i;
break;//注意要跳出
}
}
return result;
}
}
496.下一个更大元素I
题解:因为元素是唯一的 所以我们开个Map来记录num2中每个数字的位置 之后来个嵌套for就OK了
class Solution {
public int[] nextGreaterElement(int[] nums1, int[] nums2) {
int [] results = new int[nums1.length];
Map<Integer,Integer> position = new HashMap<Integer, Integer>();
for(int i=0;i<nums2.length;i++){
position.put(nums2[i],i);//因为元素是唯一的 所以开个Map来记录nums2每个数的位置
}
for(int i=0;i<nums1.length;i++){
int w = position.get(nums1[i]);
results[i]=-1;
for(int j=w;j<nums2.length;j++){
if(nums2[j]>nums1[i]){
results[i]=nums2[j];
break;
}
}
}
return results;
}
}
884.两句话中的不常见单词
题解:其中一个句子出现一次 另一个句子没有出现可以理解为只出现了一次 所以我们用一个Map来记录次数
class Solution {
Map<String,Integer> map = new HashMap<String, Integer>();
Set<String> set = new HashSet<String>();
public String[] uncommonFromSentences(String A, String B) {
List<String> results = new ArrayList<String>();
init(A,map);
init(B,map);
for(String str:set){
if(map.containsKey(str)&&(map.get(str)==1)){
results.add(str);
}
}
return results.toArray(new String[results.size()]);
}
private void init(String strs, Map<String, Integer> map) {
for(String str:strs.split(" ")){
set.add(str);
if(map.get(str)==null){
map.put(str,1);
}else{
int num = map.get(str);
map.put(str,++num);
}
}
}
}
824.山羊拉丁文
题解:就是先用空格分开,之后判断首字符是否是元音 进行对应的操作
class Solution {
StringBuilder sb = new StringBuilder();
public String toGoatLatin(String S) {
String [] strs = S.split(" ");
for(int i=0;i<strs.length;i++){
if(isyuanyin(strs[i].charAt(0))){
add(strs[i],i+1);
}else{
char a=strs[i].charAt(0);
String s = strs[i].substring(1);
add(new StringBuilder(s).append(a).toString(),i+1);
}
if(i!=strs.length-1){
sb.append(" ");
}
}
return sb.toString();
}
public boolean isyuanyin(char a){
if(a=='a'||a=='e'||a=='i'||a=='o'||a=='u'||a=='A'||a=='E'||a=='I'||a=='O'||a=='U'){
return true;
}
return false;
}
public void add(String str,int length){
sb.append(str);
sb.append("ma");
for(int i=0;i<length;i++){
sb.append("a");
}
}
}
13.罗马数字转整数
题解:就一个Map来存储对应的数字 因为前面罗马数字小于后面罗马数字只有6种情况而且对应长度只可能是2 所以就简单了
class Solution {
Map<String,Integer> map = new HashMap<String, Integer>();
public int romanToInt(String s) {
int result = 0;
init();
int i=0;
for(i=0;i<s.length();i++){
if((i<=s.length()-2)&&(map.get(String.valueOf(s.charAt(i)))<map.get(String.valueOf(s.charAt(i+1))))){
String key = Character.toString(s.charAt(i))+Character.toString(s.charAt(i+1));
System.out.println(key);
result+=map.get(key);
i++;
}
else{
result+=map.get(Character.toString(s.charAt(i)));
}
}
return result;
}
private void init() {
String [] keys={"I","V","X","L","C","D","M","IV","IX","XL","XC","CD","CM"};
int [] values={1,5,10,50,100,500,1000,4,9,40,90,400,900};
for(int i=0;i<keys.length;i++){
map.put(keys[i],values[i]);
}
}
}
796.旋转字符串
题解:因为是串A经过N次旋转后能形成串B,所以我们不妨串A+串A,这样如果串B包含在这个新字符串中,那么意味着串B能够经过串A旋转形成 如果不包含则说明不行
class Solution {
public boolean rotateString(String A, String B) {
if(A.length()==0&&B.length()==0){
return true;
}
if(A.length()!=B.length()){
return false;
}
if((A+A).contains(B)){
return true;
}else{
return false;
}
}
}
896.单调数列
题解:这题运用到了数学中的知识,先作差然后在相乘判断符号来判断是否是单调数列
class Solution {
public boolean isMonotonic(int[] A) {
if(A.length<=2) //长度小于等于2 肯定是单调数列
return true;
boolean result = true;
int cha1 = A[1]-A[0];
for(int i=2;i<A.length;i++){
int cha2=A[i]-A[i-1];
if(cha2==0){//差为0会影响判断 继续下一个
continue;
}
if(cha1*cha2<0){
result = false;
break;
}
cha1=cha2;
}
return result;
}
}
747.至少是其他数字两倍的最大数
题解:用一个for循环就可以了 找最大数 和 仅次于最大数的数 比较最大数是否是该数的两倍就行了
class Solution {
public int dominantIndex(int[] nums) {
if(nums.length==1){
return 0;
}
int max=-1;//最大的数
int p=-1; //位置
int secondmax = -1;
for(int i=0;i<nums.length;i++){
if(max<nums[i]){//最大数小于当前数
secondmax=max;
max=nums[i];
p=i;
}
else if(nums[i]>secondmax){当前数大于第二大的数
secondmax=nums[i];
}
}
return max<secondmax*2?-1:p;
}
}
200.岛屿的个数
题解:标准的dfs模板题 虽然可以用并查集做 不过有点不清楚咋用并查集解决这题 for循环遇到1就往它的四周搜索 遇到1就把它坐标变为2(意思就是走过了)
class Solution {
int count;
int []x={0,0,-1,1};
int []y={1,-1,0,0};
public int numIslands(char[][] grid) {
if(grid.length==0){
return 0;
}
count = 0;
for(int i=0;i<grid.length;i++){
for(int j=0;j<grid[i].length;j++){
if(grid[i][j]=='1'){
count++;
dfs(i,j,grid);
}
}
}
return count;
}
private void dfs(int i, int j,char [][]grid) {
for(int k=0;k<4;k++){
int xx=i+x[k];
int yy=j+y[k];
if(xx<0||yy<0||xx>=grid.length||yy>=grid[0].length){
continue;
}
if(grid[xx][yy]=='1'){
grid[xx][yy]='2';
dfs(xx,yy,grid);
}
}
}
}
695.岛屿的最大面积
题解:还是标准的dfs题 找结束条件 上下左右搜
class Solution {
int max_length;
int []xs={0,0,-1,1};
int []ys={1,-1,0,0};
public int maxAreaOfIsland(int[][] grid) {
max_length=0;
for(int i=0;i<grid.length;i++){
for(int j=0;j<grid[i].length;j++){
if(grid[i][j]==1){
int length = dfs(i,j,grid);
max_length=length>max_length?length:max_length;
}
}
}
return max_length;
}
private int dfs(int x, int y,int[][] grid) {
if(x<0||y<0||x>=grid.length||y>=grid[0].length||grid[x][y]!=1)//结束条件
return 0;
int length = 1;
grid[x][y]=0;//标记走过
for(int i=0;i<4;i++){
length+=dfs(x+xs[i],y+ys[i],grid);//上下左右搜
}
return length;
}
}
733.图像渲染
题解:依然是典型的dfs模板题 搜过的不能再搜了 所以开个boolean变量来记录
class Solution {
int [] [] results;
boolean [] [] flags;
int color;
int []x={0,0,-1,1};
int []y={1,-1,0,0};
public int[][] floodFill(int[][] image, int sr, int sc, int newColor) {
results=image;
flags = new boolean[image.length][image[0].length];
color = image[sr][sc];//原始点的颜色
results[sr][sc]=newColor; //把开始点换上新颜色
flags[sr][sc]=true; //把开始点标记为走过
dfs(sr,sc,newColor);
return results;
}
private void dfs(int sr, int sc,int newcolor) {
for(int i=0;i<4;i++){
int xx=sr+x[i];
int yy=sc+y[i];
if(xx<0||yy<0||xx>=results.length||yy>=results[0].length||results[xx][yy]!=color||flags[xx][yy]){
continue;
}
results[xx][yy]=newcolor;//把这点换上新颜色
flags[xx][yy]=true;//把这点标记为走过
dfs(xx,yy,newcolor);
}
}
}
980. 不同路径 III
题解:最近一直在做dfs的题 还是一如既往的办法
class Solution {
int length;//记录多少次
int count;//记录0出现次数 因为要求每一个无障碍方格都要通过一次
int xs[]={0,0,-1,1};
int ys[]={1,-1,0,0};
boolean [][] flags;//标记走过没
public int uniquePathsIII(int[][] grid) {
length=0;
int sx=0,sy=0;
count=0;
flags = new boolean[grid.length][grid[0].length];
for(int i=0;i<grid.length;i++){
for(int j=0;j<grid[i].length;j++){
if(grid[i][j]==0){
count++;
}
if(grid[i][j]==1){
sx=i;
sy=j;
}
}
}
flags[sx][sy]=true;
dfs(sx,sy,grid);
return length;
}
private void dfs(int x, int y,int [][]grid) {
if(grid[x][y]==2&&count==-1){//注意为什么是-1 因为你走到2把2的也减掉了
length++;
return;
}
for(int i=0;i<4;i++){
int xx=x+xs[i];
int yy=y+ys[i];
if(xx<0||yy<0||xx>=grid.length||yy>=grid[0].length||flags[xx][yy]){
continue;
}
if(grid[xx][yy]!=-1){
count--;
flags[xx][yy] = true;
dfs(xx, yy, grid);
flags[xx][yy] = false;
count++;
}
}
}
}
542.01矩阵
题解:找出每个元素到最近的 0 的距离 根据题目提示的输入输出当原数为0时 直接是0 不是0的点则用bfs就搜距离当前最近的0的距离
class Solution {
int[][] lengths;
int[] dx = {0, 0, -1, 1};
int[] dy = {1, -1, 0, 0};
public int[][] updateMatrix(int[][] matrix) {
lengths = new int[matrix.length][matrix[0].length];
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
if (matrix[i][j] != 0) {
lengths[i][j] = bfs(i, j, matrix);
}
}
}
return lengths;
}
private int bfs(int x,int y,int [][]matrix){
int sum=0;
Queue<int []> q = new LinkedList<>();//创建一个队列
q.offer(new int[]{x,y});//把当前坐标位置放到队列之中
while(q.size()!=0){//队列为空结束循环
int len=q.size();//取出当前队列的长度
sum++; //长度+1
for(int i=0;i<len;i++){
int[]n=q.poll();//取出队列中首位元素
for(int j=0;j<4;j++){//上下左右搜索
int xx=n[0]+dx[j];
int yy=n[1]+dy[j];
if(xx<0||yy<0||xx>=matrix.length||yy>=matrix[0].length){
continue;
}
if(matrix[xx][yy]==0){//当等于0就走人
return sum;
}
else{
q.offer(new int[]{xx,yy});//不是0就将这个坐标加到队列中
}
}
}
}
return sum;
}
}
994.腐烂的橘子
题解:首先这题并没有告诉你腐烂的橘子初始的时候有多少个,所以你只能用循环把腐烂的橘子加入队列中
用一个数来记录新鲜的橘子的个数
当新鲜橘子个数为0直接返回 如果不为0 就用bfs去搜 一旦当新鲜橘子为0就直接返回
当队列为空 但是新鲜橘子还不为0时 就返回-1 表示不可能
class Solution {
int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};
Queue<int []> queue;
int count;
public int orangesRotting(int[][] grid) {
queue = new LinkedList<>();
count=0;
for(int i=0;i<grid.length;i++){
for(int j=0;j<grid[i].length;j++){
if(grid[i][j]==2){
queue.offer(new int[]{i,j});
}
if(grid[i][j]==1){
count++;
}
}
}
if(count==0){
return 0;
}
return bfs(grid);
}
private int bfs(int [][]grid) {
int sum=0;
while(queue.size()!=0){
int len = queue.size();
sum++;
for(int i=0;i<len;i++){
int []n=queue.poll();
for(int j=0;j<4;j++){
int xx=n[0]+dx[j];
int yy=n[1]+dy[j];
if(xx<0||xx>=grid.length||yy<0||yy>=grid[0].length||grid[xx][yy]!=1){
continue;
}
count--;
if(count==0){
return sum;
}
System.out.println(count);
grid[xx][yy]=2;
queue.offer(new int[]{xx,yy});
}
}
}
return -1;
}
}
118.杨辉三角
题解:这个就应该没啥可以说的吧。。。编程中的入门题了
class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> list = new ArrayList<>();
int [][]dp = new int[numRows][numRows];
for(int i=0;i<numRows;i++){
List<Integer> li = new ArrayList<>();
for(int j=0;j<=i;j++){
if(j==0||i==j){
dp[i][j]=1;
}else{
dp[i][j]=dp[i-1][j-1]+dp[i-1][j];
}
li.add(dp[i][j]);
}
list.add(li);
}
return list;
}
}
566.重塑矩阵
题解:首先找出无法重塑新矩阵的条件 之后就开个数组双层for来重新给另外一个数组赋值 返回这个数组就OK了
class Solution {
public int[][] matrixReshape(int[][] nums, int r, int c) {
if(r*c!=nums.length*nums[0].length){
return nums;
}
int [][] result = new int[r][c];
int l1=0,l2=0;
for(int i=0;i<nums.length;i++){
for(int j=0;j<nums[i].length;j++){
result[l1][l2]=nums[i][j];
l2++;
if(l2==c){
l2=0;
l1++;
}
}
}
return result;
}
}
171.Excel表列序号
题解:这题没其他办法 你只有用笔来算算 模拟出对应的公式
A 1
AB 1*26+2
AAB 1*26*26+1*26+2
BBZ 2*26*26+ 2*26+26
class Solution {
public int titleToNumber(String s) {
int result = 0;
int count = 1;
for(int i=s.length()-1;i>=0;i--){
int c = s.charAt(i)-64;
if(i!=s.length()-1){
count*=26;//这样做就懒得每次for浪费时间了
}
result=result+(c*count);
}
return result;
}
}
520.检测大写字母
题解:判断首个字母和第二个字母 分别进行校验
class Solution {
public boolean detectCapitalUse(String word) {
if(word.length()==1){
return true;
}
boolean flag = true;
char first = word.charAt(0);
char second = word.charAt(1);
if(first>='a'&&first<='z'){//首字母小写
flag = isDanCi(word,'A',1);
}else{
if(second>='a'&&first<='z'){
flag = isDanCi(word,'A',1);
}else{
flag = isDanCi(word,'a',1);
}
}
return flag;
}
private boolean isDanCi(String word, char a, int m) {
for(int i=m;i<word.length();i++){
if(word.charAt(i)>=a&&word.charAt(i)<=(a+25)){
return false;
}
}
return true;
}
}
811.子域名访问计数
题解:就是计算出域名访问次数,最后把访问次数+" "+域名放到List集合去 先用map来存储 增加for遍历给出的次数+域名,放到map中 然后对域名进行处理 截取.之后为新的域名在用map来存储 最后把map转list
class Solution {
Map<String,Integer> map = new HashMap<>();
public List<String> subdomainVisits(String[] cpdomains) {
for(String cpdomain:cpdomains){
int count = Integer.valueOf(cpdomain.split(" ")[0]);
String ip = cpdomain.split(" ")[1];
addmap(ip,count);
for(int i=0;i<ip.length();i++){
if(ip.charAt(i)=='.'){
String newip = ip.substring(i+1,ip.length());
addmap(newip,count);
}
}
}
List<String> list = new ArrayList<>();
for(String key:map.keySet()){
list.add(map.get(key)+" "+key);
}
return list;
}
public void addmap(String ip,int count){
if(map.containsKey(ip)){
int num = map.get(ip)+count;
map.put(ip,num);
}else{
map.put(ip,count);
}
}
}
509.斐波那契数列(递归、动态规划)
题解:斐波那契数列是在编程中比较出名的例子,我用两种方法来说下如何解决这道题 第一种是最常见的就是递归了
class Solution {
public int fib(int N) {
if(N==0)
return 0;
if(N==1)
return 1;
return fib(N-1)+fib(N-2);
}
}
另一种就是dp(动态规划)
class Solution {//动态规划来做用时大大降低
public int fib(int N) {
int []a=new int[31];
a[0]=0;
a[1]=1;
for(int i=2;i<=30;i++){
a[i]=a[i-1]+a[i-2];
}
return a[N];
}
}
771.宝石与石头
题解:就是从S中找有几个是J中的 双重for就ok
class Solution {
public int numJewelsInStones(String J, String S) {
int result = 0;
for(int i=0;i<J.length();i++)
{
for(int j=0;j<S.length();j++)
{
if(J.charAt(i)==S.charAt(j)){
result++;
}
}
}
return result;
}
}
709.转换成小写字母
题解:从题意中我们就知道这题怎么做了…
class Solution {
public String toLowerCase(String str) {
StringBuilder sb=new StringBuilder(str);
for(int i=0;i<sb.length();i++){
if(sb.charAt(i)>='A'&&sb.charAt(i)<='Z'){
char temp = (char)(sb.charAt(i)+32);
sb.setCharAt(i, temp);
}
}
return sb.toString();
}
}