日常算法题(二)

给定两个字符串s和t,确定它们是否是同构的。
如果s中的字符可以替换为t,则两个字符串是同构的。
所有出现的字符必须替换为另一个字符,同时保留字符的顺序。没有两个字符可以映射到相同的字符,但字符可以映射到自身。

例1:
输入: s = “egg”, t =“add”
输出: true
例2:
输入: s = “foo”, t =“bar”
输出: false

可以使用HashMap,把字符t变成字符串

public boolean isIsomorphic(String s, String t) {
    Map m = new HashMap();
    for (Integer i=0; i<s.length(); ++i)
        if (m.put(s.charAt(i), i) != m.put(t.charAt(i)+"", i))
            return false;
    return true;
}

如果阵列单调递增或单调递减,则阵列是单调的。
数组A是单调的,如果所有的增加i <= j,A[i] <= A[j]。A如果对所有人来说i <= j,数组是单调减少的A[i] >= A[j]。
返回true当且仅当给定的数组A是单调的。

例1:
输入:[1,2,2,3]
输出:true
例2:
输入:[6,5,4,4]
输出:true

    public boolean isMonotonic(int[] A) {
        boolean in = true, de = true;
        for(int i = 0; i < A.length-1; i++) {
            if(A[i] > A[i+1]) in = false;
            else if(A[i] < A[i+1]) de = false;
        }
        return in || de;
    }

给定两个串 S 并T,返回,如果他们是平等的,当两者都输入到空的文本编辑器。#表示退格字符。

例1:
输入: S = “ab#c”,T = “ad#c”
输出:true
说明:S和T都变为“ac”。
例2:
输入: S = “ab ##”,T = “c#d#”
输出:true
说明:S和T都变为“”。

可以考虑使用堆栈来进行操作

   public boolean backspaceCompare(String S, String T) {
        for (int i = S.length() - 1, j = T.length() - 1;; i--, j--) {
            for (int b = 0; i >= 0 && (b > 0 || S.charAt(i) == '#'); --i) b += S.charAt(i) == '#' ? 1 : -1;
            for (int b = 0; j >= 0 && (b > 0 || T.charAt(j) == '#'); --j) b += T.charAt(j) == '#' ? 1 : -1;
            if (i < 0 || j < 0 || S.charAt(i) != T.charAt(j)) return i == -1 && j == -1;
        }
    }

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

public int maxSubArray(int [] nums) {
		
		if(nums == null||nums.length == 0)
			return 0;
		int current = nums[0],max = nums[0];
		
		for(int i = 1;i < nums.length;i++){
			
			current = Math.max(current + nums[i], nums[i]);
			max = Math.max(current, max);
		}
		return max;

编写一个程序判断给定的数是否为丑数。
丑数就是只包含质因数 2, 3, 5 的正整数。

示例 1:
输入: 64.
输出: true
解释: 6 = 2 × 3
示例 2:
输入: 8
输出: true
解释: 8 = 2 × 2 × 2
示例 3:
输入: 14
输出: false
解释: 14 不是丑数,因为它包含了另外一个质因数 7。
说明:
1 是丑数。输入不会超过 32 位有符号整数的范围: [−231, 231 − 1]。

public boolean isUgly(int num) {
		
		while(num % 2 == 0)
			num = num / 2;
		while(num % 3 == 0)
			num = num / 3;
		while(num % 5 == 0)
			num = num / 5;
		
		return (num == 1) ? false : true;

给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。

public int [] plusOne(int [] digits) {
		
		int len = digits.length;
		for(int i = len - 1;i >= 0;i--) {
			if(digits[i] < 9) {
			
				digits[i]++;
				return digits;
			}
			digits[i] = 0;
		}
		
		int [] nums = new int [len + 1];
		nums[0] = 1;
		return nums;
	}

给定已排序的链接列表,删除所有重复项,使每个元素只出现一次。

例1:
输入: 1-> 1-> 2
输出: 1-> 2
例2:
输入: 1-> 1-> 2-> 3-> 3
输出: 1-> 2-> 3

public ListNode deleteDuplicates(ListNode head) {
		
       if(head == null||head.next == null) return head;
       
       ListNode node = head;
       while(node.next != null) {
    	   
    	   if(node.val == node.next.val) node.next = node.next.next;
    	   
    	   else  node = node.next;
       }
       
       return head;

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

public int singleNumber(int [] nums){
		
		int len = nums.length;
		int max = nums[0];
		int a = 0;
		for(int i = 1;i < len;i++){
			
			if(max < nums[i])
				max = nums[i];
		}
		
		int [] acg = new int [max];
		for(int i = 0;i < max + 1;i++)
			acg[i] = 0;
		
		for(int j = 0;j < len;j++) {
			
			acg[nums[j]]++;
		}
		
		for(int i = 0;i < max + 1;i++) {
			
			if(acg[i] == 1)
				a = i;
		}
		return a;
	}

9.组合总数:

给定候选数字(candidates)和目标数字(target)的集合,找到candidates 候选数字相加的所有唯一组合target。
每个数字candidates 只能在组合中使用一次。
注意:
所有数字(包括target)都是正整数。
解决方案集不得包含重复的组合。

例1:
输入: candidate = [10,1,2,7,6,1,5],target = 8,
解决方案集是:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
例2:
输入:候选= [2,5,2,1,2],目标= 5,
解集是:
[
[1,2,2],
[5]
]

可以考虑使用回溯算法,创建一个递归树,使用基于元素的回溯法,从小到大,并决定我在结果组合中包含的每个元素的副本数量。

    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort (candidates);
        List<List<Integer>> res_lss = new ArrayList<> ();
        search (candidates, 0, target, res_lss, new ArrayDeque<> ());
        return res_lss;
    }

    void search (int[] candidates, int index, int remain, List<List<Integer>> lss, Deque<Integer> accum) {
        if (remain == 0) {
            lss.add (new ArrayList<> (accum));
            return;
        }
        if (index >= candidates.length) {
            return;
        }
        int next = index;
        while (next < candidates.length && candidates[next] == candidates[index])
            next++;
        int num = next - index, cur = candidates[index], i;
        for (i = 0; i <= num && remain >= i * cur; i++) {
            if (i > 0)
                accum.push (cur);
            search (candidates, next, remain - i * cur, lss, accum);
        }
        assert accum.size () >= i - 1;
        for (int j = 0; j < i - 1; j++)
            accum.pop ();
    }

10.转移信件:

我们有一串S小写字母和一个整数数组shifts。

调用一个字母的移位,字母表中的下一个字母,(环绕以便’z’变为’a’)。

例如,shift(‘a’) = 'b’和shift(‘t’) = ‘u’,和shift(‘z’) = ‘a’。

现在,每一个shifts[i] = x,我们要移后的第一i+1 字母S,x倍。

S应用所有这些转换后返回最后一个字符串。

例1:
输入: S =“abc”,shift = [3,5,9]
输出: “rpl”
说明:
我们从“abc”开始。
将S的前1个字母移动3后,我们有“dbc”。
将S的前2个字母移动5后,我们有“igc”。
在将S的前三个字母移动9后,我们得到了“rpl”,即答案。
注意:
1 <= S.length = shifts.length <= 20000
0 <= shifts[i] <= 10 ^ 9


class Solution {
    public String shiftingLetters(String S, int[] shifts) {
        char[] arr = S.toCharArray();
        int shift = 0;
        for (int i = arr.length - 1; i >= 0; i--) {
            shift = (shift + shifts[i]) % 26;
            arr[i] = (char)((arr[i] - 'a' + shift) % 26 + 'a');
        }
        return new String(arr);
    }
}

11.字符串中的排序:

给定两个字符串s1和s2,如果s2包含s1的排列,则写一个函数返回true 。换句话说,第一个字符串的排列之一是第二个字符串的子字符串。

例1: 输入: s1 =“ab”s2 =“eidbaooo” 输出: True 说明: s2包含s1(“ba”)的一个排列。
例2:输入: s1 =“ab”s2 =“eidboaoo” 输出: False

可以考虑先创建一个保存字符串的数组,再创建一个移动数组,在每次迭代期间告诉数组是否相等

public boolean checkInclusion(String s1, String s2) {
        int n1=s1.length(),n2=s2.length();
        int[] f1=new int[26];
        for(int i=0;i<n1;i++) f1[s1.charAt(i)-'a']++;
        
        int[] f2=new int[26];
        for(int j=0;j<n2;j++){
            f2[s2.charAt(j)-'a']++;
            if(j>=n1) f2[s2.charAt(j-n1)-'a']--;
            if(Arrays.equals(f2,f1)) return true;
        }
        return false;
    }

12.实现 atoi,将字符串转为整数。

该函数首先根据需要丢弃任意多的空格字符,直到找到第一个非空格字符为止。如果第一个非空字符是正号或负号,选取该符号,并将其与后面尽可能多的连续的数字组合起来,这部分字符即为整数的值。如果第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。

字符串可以在形成整数的字符后面包括多余的字符,这些字符可以被忽略,它们对于函数没有影响。

当字符串中的第一个非空字符序列不是个有效的整数;或字符串为空;或字符串仅包含空白字符时,则不进行转换。

若函数不能执行有效的转换,返回 0。

说明:

假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231 − 1]。如果数值超过可表示的范围,则返回
INT_MAX (231 − 1) 或 INT_MIN (−231) 。

示例 1:

输入: “42” 输出: 42 示例 2:

输入: " -42" 输出: -42 解释: 第一个非空白字符为 ‘-’, 它是一个负号。
我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。 示例 3:

输入: “4193 with words” 输出: 4193 解释: 转换截止于数字 ‘3’ ,因为它的下一个字符不为数字。 示例 4:

输入: “words and 987” 输出: 0 解释: 第一个非空字符是 ‘w’, 但它不是数字或正、负号。
因此无法执行有效的转换。 示例 5:

输入: “-91283472332” 输出: -2147483648 解释: 数字 “-91283472332” 超过 32
位有符号整数范围。
因此返回 INT_MIN (−231) 。

想法:可以通过条件逐一进行条件判断

public class Solution {
	  public int myAtoi(String str) {
			
			int i = 1;
			String s = "";
			if(str.length() == 0||str == null)
				return 0;
			while(i <= str.length()) {
				
				if((int)str.charAt(i) != 32) {
					if((int)str.charAt(i) > 48||(int)str.charAt(i) <= 57)
						s += str.charAt(i);
					else if((int)str.charAt(i) == 48)
						s += "";
					else
						return 0;
					
					break;
				}
				
				i++;
			}
			
			i++;
			while(i <= str.length()) {
				
				if((int)str.charAt(i) >= 48||(int)str.charAt(i) <= 57)
					s += str.charAt(i);
				i++;
			}
			
			long t = Long.parseLong(s);
			if(t < Math.pow(-2, 31)||t > Math.pow(2, 31))
				return 0;
			else
				return (int)t;
		}

	    public static String stringToString(String input) {
	        if (input == null) {
	            return "null";
	        }
	        return Json.value(input).toString();
	    }
	    
	    public static void main(String[] args) throws IOException {
	        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	        String line;
	        while ((line = in.readLine()) != null) {
	            String str = stringToString(line);
	            
	            int ret = new Solution3().myAtoi(str);
	            
	            String out = String.valueOf(ret);
	            
	            return out;
	        }
	    }

13.救人的小船:

第i- 人有重量people[i],每艘船可以承受最大重量limit。

每艘船最多同时载有2人,前提是这些人的重量总和最多limit。

返回携带每个人的最小船只数量。(保证每个人都可以乘船。)

例1:

输入:人= [1,2],限制= 3 输出:1 说明: 1船(1,2) 例2:

输入: people = [3,2,2,1],limit = 3 输出:3 说明:3艘船(1,2),(2)和(3) 例3:

输入:人= [3,5,3,4],限制= 5 输出:4 说明:4船(3),(3),(4),(5) 注意:

1 <= people.length <= 50000 1 <= people[i] <= limit <= 30000

可以从两端开始排序,总是移动高端,但低端取决于它是否可以塞进高端的船

 public int numRescueBoats(int[] people, int limit) {
        Arrays.sort(people);
        int ans = 0; 
        for (int hi = people.length - 1, lo = 0; hi >= lo; --hi, ++ans) { 
            if (people[lo] + people[hi] <= limit) { ++lo; }
        }
        return ans;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值