LeetCode 27 removes elements & 28 to achieve strStr() & 29 division

Maintenance fortunate bitter, public concern if punch welcome No bigsaireply into the group, if any help welcome thumbs up support!

Remove element

Given an array of nums and a value of val, you need to remove all the elements whose value is equal to val in place, and return the new length of the removed array.
Don't use extra array space, you must use only O(1) extra space and modify the input array in-situ.
The order of the elements can be changed. You don't need to consider the elements in the array beyond the new length.

Example 1:

Given nums = [3,2,2,3], val = 3, the
function should return the new length 2, and the first two elements in nums are both 2.
You don't need to consider the elements in the array beyond the new length.

Example 2:

Given nums = [0,1,2,2,3,0,4,2], val = 2, the
function should return the new length of 5, and the first five elements in nums are 0, 1, 3, 0 , 4.
Note that these five elements can be in any order.
You don't need to consider the elements in the array beyond the new length.

Description:

Why is the return value an integer, but the output answer is an array?
Please note that the input array is passed by "reference", which means that modifying the input array in the function is visible to the caller.
You can imagine the internal operation as follows:
// nums is passed by "reference". In other words, do not make any copy of the actual parameters
int len ​​= removeElement(nums, val);
// Modifying the input array in the function is visible to the caller.
// According to the length returned by your function, it will print out all the elements in the array within that length range.
for (int i = 0; i <len; i++) { print(nums[i]); }

Analysis:
Use an index to mark the current real position. During the traversal process, if the current position value is not equal to the target value, then assign a value, and if it is equal to the data to be deleted, skip no assignment. This is the process of traversing a re-assignment.

The ac code is:

public int removeElement(int[] nums, int val) {
    
    
	 int index=0;
	 
	 for(int i=0;i<nums.length;i++)
	 {
    
    
		 if(nums[i]==val)
			 continue;
		 nums[index++]=nums[i];
	 }
	 return index;
  }

Insert picture description here

Implement strStr()

Title description:

Given a haystack string and a needle string, find the first position (starting from 0) where the needle string appears in the haystack string. If it does not exist, -1 is returned.

Example 1:

Input: haystack = "hello", needle = "ll"
Output: 2

Example 2:

Input: haystack = "aaaaa", needle = "bba"
Output: -1

Description:

When needle is an empty string, what value should we return? This is a good question in an interview.
For this question, we should return 0 when needle is an empty string. This is consistent with the definition of strstr() in C language and indexOf() in Java

Analysis
Due to the amount of data, the efficiency of using the KMP algorithm in this question is not very good (KMP requires preprocessing), on the contrary, the efficiency of using the ordinary method is very high. The effect of using the sunday algorithm is also relatively ordinary, which is amazing.

Ordinary matching, also known as double pointer or something, is actually a violent match, but the official method given by the same violent match is much faster. Personal writing is:

public int strStr(String haystack, String needle) {
    
    
	      if(needle==null||"".equals(needle))
		     return 0;
	      char a[]=haystack.toCharArray();
	      char b[]=needle.toCharArray();
		  for(int i=0;i<a.length-b.length+1;i++)
		  {
    
    
              int j=-1;
			  while(j++<b.length)
			  {
    
    
				  if(a[i+j]!=b[j])
				  {
    
    
					  break;
				  }
				  if(j==b.length-1)
					  return i; 
			 }
			  
		  }
		  return -1;
 }

Insert picture description here
The official succinct wording:

public int strStr(String haystack, String needle) {
    
    
    int L = needle.length(), n = haystack.length();
    for (int start = 0; start < n - L + 1; ++start) {
    
    
      if (haystack.substring(start, start + L).equals(needle)) {
    
    
        return start;
      }
    }
    return -1;
  }

The author has also implemented the kmp method, but due to the general data problem, the kmp algorithm will not be introduced in detail here:

 public  int[] getNext(String needle) {
    
    
		    char[] p = needle.toCharArray();
		    int[] next = new int[p.length];
		    next[0] = -1;
		    int j = 0;
		    int k = -1;
		    while (j < p.length - 1) {
    
    
		       if (k == -1 || p[j] == p[k]) {
    
    
		           next[++j] = ++k;
		       } else {
    
    
		           k = next[k];
		       }
		    }
		    return next;
		}
	  public  int KMP(String haystack, String needle) {
    
    
		     char[] t = haystack.toCharArray();
		    char[] p = needle.toCharArray();
		    int i = 0; // 主串的位置
		    int j = 0; // 模式串的位置
		    int[] next = getNext(needle);
		    while (i < t.length && j < p.length) {
    
    
		       if (j == -1 || t[i] == p[j]) {
    
     // 当j为-1时,要移动的是i,当然j也要归0
		           i++;
		           j++;
		       } else {
    
    
		           // i不需要回溯了
		           // i = i - j + 1;
		           j = next[j]; // j回到指定位置
		       }
		       if(j==p.length) {
    
    return i-j;}
		    }
		    return -1;
		}
	  public int strStr(String haystack, String needle) {
    
    
		  if(needle==null||"".equals(needle))
		     return 0;
		 
		  return KMP(haystack, needle);
	 }

Insert picture description here
The same use of the sunday algorithm (will be specifically explained later) is also general

 public  int strStr(String haystack, String needle) {
    
    
		  if(needle==null||"".equals(needle))
			     return 0;
		  int lastchar[]=new int [200];
		  char a[]=haystack.toCharArray();
		  char p[]=needle.toCharArray();
		  for(int i=0;i<p.length;i++)
		  {
    
    
			  lastchar[p[i]]=i+1;
		  }
		  int i=0;
		  int j=0;
		 int len=a.length-p.length+1;
		  while (i<a.length) {
    
    
			 int index=i-(lastchar[a[i]]-1);//a[i] 字符
			if(lastchar[a[i]]!=0&&index>=0&&index<len)//可以匹配
			{
    
    
				while (j<p.length) {
    
    //尝试匹配
					if(p[j]!=a[index+j])
						break;
					j++;
				}
				if(j==p.length)
				{
    
    
					return index;
				}
				else {
    
    
					i=index+p.length;
					j=0;
				}
			}
			else {
    
    
				i++;
			}
		}
		  
		return -1;
	}

Insert picture description here

Divide two numbers

Title description

Given two integers, the dividend and the divisor. Divide two numbers without using multiplication, division, and mod operators.
Returns the quotient obtained by dividing the dividend by the divisor.
The result of integer division should be truncated (truncate) the decimal part, for example: truncate(8.345) = 8 and truncate(-2.7335) = -2

Example 1:

Input: dividend = 10, divisor = 3
Output: 3
Explanation: 10/3 = truncate(3.33333…) = truncate(3) = 3

Example 2:

Input: dividend = 7, divisor = -3
Output: -2
Explanation: 7/-3 = truncate(-2.33333…) = -2

prompt:

Both the dividend and the divisor are 32-bit signed integers.
The divisor is not zero.
Assuming that our environment can only store 32-bit signed integers, the value range is [−2^31, 2^31 − 1]. In this question, if the division result overflows, it returns 2^31 − 1.

Analysis
Need to calculate the value of division, and also encountered the following problems:

  • Value may be out of range
  • Cannot use multiplication and division

The problem of value out-of-bounds can be considered in special circumstances. But how can we know the result of division if we cannot use multiplication and division?

Method 1: Addition and accumulation
This is probably the most stupid method. Divide by a few, then use this number to superimpose to find the result.
Insert picture description here
Of course, if the number is large, the divisor of 1, 2 will be very slow, and only ac can be forced .

public static int divide(int dividend, int divisor) {
    
    
		int zhengfu=1;
		long divd=dividend,divs=divisor;
		if(dividend>0&&divisor<0)
		{
    
    
			divs=-divisor;zhengfu=-1;
		}
		else if(dividend<0&&divisor>0)
		{
    
    
			divd=-divd;zhengfu=-1;
		}
		else if (dividend<0&&divisor<0) {
    
    
			divd=-divd;divs=-divs;
		}
	
		if(Math.abs(divd)<Math.abs(divs))return 0;
		long i=0,index=0;
		if(divs==1)i=divd+1;
		else
		while (index<=divd) {
    
    
			i++;index+=divs;
		}
		long va=(zhengfu==1?(i-1):(1-i));
		if(va>Integer.MAX_VALUE)return Integer.MAX_VALUE;
		if(va<Integer.MIN_VALUE)return Integer.MIN_VALUE;
		return (int) va;
    }

Insert picture description here
What method can be used to optimize the algorithm? This involves the issue of binary. In binary:

  • 2=0010 means there are 2 1
  • 4=0100 means there are 4 ones
  • 6=0110 means there are 4+2 1

Similarly, any number can be expressed in binary, 1101 means 8+4+1. In the same way, we will bring this idea to this question for calculation, but the basic unit is not one :
Insert picture description here
because we use addition to multiply the value by two Therefore, use this to find the maximum number in the range each time (the number of values ​​is superimposed and other variables need to be counted). After processing this part of the data, continue to operate the remaining values ​​until it stops. Of course, pruning can be considered in the specific implementation (when the divisor is ±1, the problem of positive and negative numbers and out-of-bounds should be properly solved at the same time, here we use long to deal with, turn all into positive numbers and use a mark for positive and negative).

The implementation code is:

public static int divide(int dividend, int divisor)
	{
    
    
		if(divisor==1)return dividend;
		if(divisor==-1)return dividend==Integer.MIN_VALUE?Integer.MAX_VALUE:-dividend;

		long value=0;//记录总次数结果
		int time=1;//临时每次的次数
		long divd=dividend,divs=divisor;//转成long处理
		
		int zhengfu=1;//判断是正数还是负数
		if(divd<0)
		{
    
    
			divd=-divd;zhengfu=-zhengfu;
		}
	    if(divs<0)
	    {
    
    
	    	divs=-divs;zhengfu=-zhengfu;
	    }
	    long team=divs;//临时数据2倍叠加
		while (team<=divd) {
    
    
			if(team+team>divd)
			{
    
    
				value+=time;
				divd-=team;
				team=divs;
				time=1;
				
				continue;
			}
			team+=team;
			time+=time;
			
		}
		return (int) (zhengfu==1?value:-value);
	}

Insert picture description here

Conclusion

Well, this check-in is over. Welcome to like and support. If you check-in, please follow the official account and bigsaireply to the group to join the check-in.
Insert picture description here

Guess you like

Origin blog.csdn.net/qq_40693171/article/details/108680259