Rotate Array(3 ways)

Rotate an array of n elements to the right by k steps.

For example, with n = 7 and k = 3, the array [1,2,3,4,5,6,7] is rotated to [5,6,7,1,2,3,4].Could you do it in-place with O(1) extra space?

Try to come up as many solutions as you can, there are at least 3 different ways to solve this problem.

/*方法1:将新数组与原数组比较可找出规律:k=3时即将最后3个数移动到数组最前面,
 * 相当于先将1~4逆转成4,3,2,1,再将5~7逆转成7,6,5,最后再将整个数组逆转成5,6,7,1,2,3,4。
 * 所以添加一个函数reverse()作为逆转使用。时间复杂度为O(n)
 */
public class Solution {
  public void reverse(int[] nums, int l, int h){
		int temp = 0;
		while (l < h ){
			temp = nums[l];
			nums[l ++] = nums[h];
			nums[h --] = temp;
		}
	}
  public void rotate(int[] nums, int k) {
  	int len = nums.length;
  	k %= len; //一开始是考虑对k进行判断,若k超过数组长度即报错,运行之后才发现系统默认循环移动,所以用到该语句,这是关键
  	if (k == 0){
  	    return;
  	}
  	if (len - k > 1){
  	    reverse(nums, 0, len - k - 1);
  	}
  	if (k > 1){
  	    reverse(nums, len -k, len - 1);
  	}
  	reverse(nums, 0 , len - 1);
  }
}


/*方法2:直接对数组元素依次进行移动,如k=3时,理应将5,6,7分别移动到数组最前面,
 * 一开始尝试的将7先保存到temp,然后将1~6依次后移一位,然后将6保存进temp,
 * 将1~5依次后移一位,最后将5保存进temp,然后将1~4后移。但是leetcode会报超时错误,
 * 进一步优化后,完成了下面的代码实现。时间复杂度为k * O(n - k)
 */
public class Solution {
    public void rotate(int[] nums, int k) {
    	int i = 0;
    	int temp = 0;
    	int len = nums.length;
    	k %= len;
    	for (i = 0; i < k; i ++){
    		temp = nums[len - k + i];
    		for (int j = len - k + i; j > i; j --){ 
//从5开始置temp,然后移动1~4,再将6置temp,移动1~4…这样每一步就分别省去了6,7的移动,leetcode运行通过
    			nums[j] = nums[j - 1 ];
    		}
    		nums[i] = temp;
    	}
    }
}

/*方法3:将数组元素从末尾(i = len - 1)开始每k个进行位置对换,如1,2,3,4,5,6,7,k = 3,
 * 先将5,6,7和2,3,4对换,变成1,5,6,7,2,3,4,此时i指向7,i - 3指向1的位置,
 * 继续将7和1交换,得到7,5,6,1,2,3,4,i - 3 < 0停止交换,最后将前k个数调整位置成5,6,7
 */
public class Solution {
    public void rotate(int[] nums, int k) {
    	int len = nums.length;
    	k %= len;
    	if (k == 0){
    		return;
    	}
    	int i = len - 1;
    	int temp = 0;
    	int t;
    	while (i - k >= 0){//每k个进行交换,时间复杂度为k * O(n/k) = O(n)
    		t = k;
    		while ((i - k >= 0) && (t > 0)){
    			temp = nums[i];
    			nums[i] = nums[i - k];
    			nums[i - k] = temp;
    			i --;
    			t --;
    		}
    	}
    	t = len % k;
    	if (t == 0){//若k正好能被元素个数整除,则无需再对前k个元素进行处理
    	    return;
    	}
    	else {//t不为0时,说明元素没有正好按每k个进行交换,所以前k个元素的位置需要根据t的大小进行交换,时间复杂度为(n % k) * O(k)
    		while (t > 0){
    			i = 0;
    			temp = nums[0];
    			while (i + 1 < k){
    				nums[i] = nums[i + 1];
    				i ++;
    				}
    			nums[i] = temp;
				t --;
    			}
    		}
    		return;
    }
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要绘制一个四边形绕(5,4)旋转90度,可以按照以下步骤使用转换矩阵方法: 1. 定义四边形的四个顶点坐标,可以使用数组表示,例如: ``` float vertices[] = { 4.0f, 3.0f, 0.0f, // 右上角 2.0f, 4.0f, 0.0f, // 左上角 3.0f, 2.0f, 0.0f, // 右下角 1.0f, 1.0f, 0.0f // 左下角 }; ``` 2. 创建一个旋转矩阵,将四边形绕原点逆时针旋转90度,可以使用以下代码: ``` glm::mat4 rotation = glm::rotate(glm::mat4(1.0f), glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f)); ``` 这里使用了glm库的旋转函数,第一个参数是一个4x4的单位矩阵,第二个参数是旋转角度,第三个参数是旋转轴向量,这里选择了z轴作为旋转轴。 3. 创建一个平移矩阵,将四边形平移到(5,4)的位置,可以使用以下代码: ``` glm::mat4 translation = glm::translate(glm::mat4(1.0f), glm::vec3(5.0f, 4.0f, 0.0f)); ``` 这里使用了glm库的平移函数,第一个参数是一个4x4的单位矩阵,第二个参数是平移向量。 4. 将旋转矩阵和平移矩阵相乘,得到最终的变换矩阵: ``` glm::mat4 transform = translation * rotation; ``` 5. 将变换矩阵传递给着色器,在顶点着色器中将顶点坐标乘以变换矩阵,即可实现四边形的旋转和平移,例如: ``` #version 330 core layout (location = 0) in vec3 aPos; uniform mat4 transform; void main() { gl_Position = transform * vec4(aPos, 1.0f); } ``` 6. 最后使用glDrawArrays函数绘制四边形。 完整的代码示例: ``` #include <glad/glad.h> #include <GLFW/glfw3.h> #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> #include <iostream> void framebuffer_size_callback(GLFWwindow* window, int width, int height); void processInput(GLFWwindow *window); // settings const unsigned int SCR_WIDTH = 800; const unsigned int SCR_HEIGHT = 600; const char *vertexShaderSource = "#version 330 core\n" "layout (location = 0) in vec3 aPos;\n" "uniform mat4 transform;\n" "void main()\n" "{\n" " gl_Position = transform * vec4(aPos, 1.0f);\n" "}\0"; const char *fragmentShaderSource = "#version 330 core\n" "out vec4 FragColor;\n" "void main()\n" "{\n" " FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n" "}\n\0"; int main() { // glfw: initialize and configure // ------------------------------ glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // glfw window creation // -------------------- GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL); if (window == NULL) { std::cout << "Failed to create GLFW window" << std::endl; glfwTerminate(); return -1; } glfwMakeContextCurrent(window); glfwSetFramebufferSizeCallback(window, framebuffer_size_callback); // glad: load all OpenGL function pointers // --------------------------------------- if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) { std::cout << "Failed to initialize GLAD" << std::endl; return -1; } // build and compile our shader zprogram // ------------------------------------ // vertex shader int vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertexShaderSource, NULL); glCompileShader(vertexShader); // check for shader compile errors int success; char infoLog[512]; glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(vertexShader, 512, NULL, infoLog); std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl; } // fragment shader int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL); glCompileShader(fragmentShader); // check for shader compile errors glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog); std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl; } // link shaders int shaderProgram = glCreateProgram(); glAttachShader(shaderProgram, vertexShader); glAttachShader(shaderProgram, fragmentShader); glLinkProgram(shaderProgram); // check for linking errors glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog); std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl; } glDeleteShader(vertexShader); glDeleteShader(fragmentShader); // set up vertex data (and buffer(s)) and configure vertex attributes // ------------------------------------------------------------------ float vertices[] = { 4.0f, 3.0f, 0.0f, // 右上角 2.0f, 4.0f, 0.0f, // 左上角 3.0f, 2.0f, 0.0f, // 右下角 1.0f, 1.0f, 0.0f // 左下角 }; unsigned int VBO, VAO; glGenVertexArrays(1, &VAO); glGenBuffers(1, &VBO); // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). glBindVertexArray(VAO); glBindBuffer(GL_ARRAY_BUFFER, VBO); glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind glBindBuffer(GL_ARRAY_BUFFER, 0); // You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other // VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary. // glBindVertexArray(0); // render loop // ----------- while (!glfwWindowShouldClose(window)) { // input // ----- processInput(window); // render // ------ glClearColor(0.2f, 0.3f, 0.3f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); // create transformations glm::mat4 transform = glm::translate(glm::mat4(1.0f), glm::vec3(5.0f, 4.0f, 0.0f)); transform = glm::rotate(transform, glm::radians(90.0f), glm::vec3(0.0f, 0.0f, 1.0f)); // get matrix's uniform location and set matrix unsigned int transformLoc = glGetUniformLocation(shaderProgram, "transform"); glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(transform)); // render container glUseProgram(shaderProgram); glBindVertexArray(VAO); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); // glBindVertexArray(0); // no need to unbind it every time // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.) // ------------------------------------------------------------------------------- glfwSwapBuffers(window); glfwPollEvents(); } // optional: de-allocate all resources once they've outlived their purpose: // ------------------------------------------------------------------------ glDeleteVertexArrays(1, &VAO); glDeleteBuffers(1, &VBO); glDeleteProgram(shaderProgram); // glfw: terminate, clearing all previously allocated GLFW resources. // ------------------------------------------------------------------ glfwTerminate(); return 0; } // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly // --------------------------------------------------------------------------------------------------------- void processInput(GLFWwindow *window) { if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) glfwSetWindowShouldClose(window, true); } // glfw: whenever the window size changed (by OS or user resize) this callback function executes // --------------------------------------------------------------------------------------------- void framebuffer_size_callback(GLFWwindow* window, int width, int height) { // make sure the viewport matches the new window dimensions; note that width and // height will be significantly larger than specified on retina displays. glViewport(0, 0, width, height); } ``` 在这个示例中,我们使用了GLM库来进行矩阵计算,以及glfw和glad库来创建窗口和加载OpenGL函数。在渲染循环中,我们先创建了变换矩阵,将其上传到着色器中,然后绘制四边形。要注意的是,在绘制四边形之前,我们需要先绑定VAO和使用着色器程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值